ECMA-262 草案 / 2025年5月19日

ECMAScript® 2026 语言规范

关于本规范

位于 https://tc39.es/ecma262/ 的文档是最准确和最新的 ECMAScript 规范。它包含最新年度快照的内容以及自该快照以来的所有 已完成提案 (那些在 提案流程 中达到第4阶段的提案,因此已在多个实现中实现,将包含在下一个实际修订版中)。

本文档提供 单页版多页版

为本规范做贡献

本规范在 GitHub 上借助 ECMAScript 社区的帮助进行开发。有多种方式可以为本规范的开发做出贡献:

有关本文档创建方式的更多信息,请参阅版权页

介绍

本 Ecma 标准定义了 ECMAScript 2026 语言。这是 ECMAScript 语言规范的第十七版。自 1997 年第一版发布以来,ECMAScript 已经发展成为世界上最广泛使用的通用编程语言之一。它最为人所知的是作为嵌入在 Web 浏览器中的语言,但也被广泛应用于服务器和嵌入式应用程序。

ECMAScript 基于几种原创技术,最著名的是 JavaScript(Netscape)和 JScript(Microsoft)。该语言由 Brendan Eich 在 Netscape 发明,首次出现在该公司的 Navigator 2.0 浏览器中。它出现在 Netscape 的所有后续浏览器中,以及从 Internet Explorer 3.0 开始的所有 Microsoft 浏览器中。

ECMAScript 语言规范的开发始于 1996 年 11 月。本 Ecma 标准的第一版于 1997 年 6 月由 Ecma 大会通过。

该 Ecma 标准已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并于 1998 年 4 月批准为国际标准 ISO/IEC 16262。1998 年 6 月的 Ecma 大会批准了 ECMA-262 的第二版,以保持与 ISO/IEC 16262 完全一致。第一版和第二版之间的变化在性质上是编辑性的。

该标准的第三版引入了强大的正则表达式、更好的字符串处理、新的控制语句、try/catch 异常处理、更严格的错误定义、数值输出格式化以及为预期的未来语言增长而进行的小幅更改。ECMAScript 标准的第三版于 1999 年 12 月由 Ecma 大会通过,并于 2002 年 6 月作为 ISO/IEC 16262:2002 发布。

第三版发布后,ECMAScript 与万维网结合实现了大规模应用,成为几乎所有 Web 浏览器支持的编程语言。为开发 ECMAScript 第四版做了大量工作。然而,这项工作没有完成,也没有作为 ECMAScript 第四版发布,但其中一些内容被纳入了第六版的开发中。

ECMAScript 第五版(作为 ECMA-262 第 5 版发布)编纂了在浏览器实现中已经常见的语言规范的事实解释,并增加了对自第三版发布以来出现的新功能的支持。这些功能包括访问器属性、对象的反射创建和检查、属性特性的程序控制、额外的数组操作函数、对 JSON 对象编码格式的支持,以及提供增强错误检查和程序安全性的严格模式。第五版于 2009 年 12 月由 Ecma 大会通过。

第五版已提交给 ISO/IEC JTC 1,按照快速通道程序通过,并批准为国际标准 ISO/IEC 16262:2011。ECMAScript 标准的 5.1 版纳入了小幅更正,与 ISO/IEC 16262:2011 文本相同。5.1 版于 2011 年 6 月由 Ecma 大会通过。

第六版的重点开发始于 2009 年,当时第五版正在准备发布。然而,这之前进行了大量的实验和语言增强设计工作,可以追溯到 1999 年第三版的发布。从很真实的意义上说,第六版的完成是十五年努力的顶峰。这一版的目标包括为大型应用程序、库创建以及将 ECMAScript 用作其他语言的编译目标提供更好的支持。它的一些主要增强功能包括模块、类声明、词法块作用域、迭代器和生成器、用于异步编程的 promise、解构模式和适当的尾调用。ECMAScript 内置库得到扩展,支持额外的数据抽象,包括映射、集合和二进制数值数组,以及对字符串和正则表达式中 Unicode 补充字符的额外支持。内置功能也通过子类化变得可扩展。第六版为常规的、增量的语言和库增强提供了基础。第六版于 2015 年 6 月由大会通过。

ECMAScript 2016 是在 Ecma TC39 新的年度发布节奏和开放开发过程下发布的第一个 ECMAScript 版本。从 ECMAScript 2015 源文档构建了一个纯文本源文档,作为完全在 GitHub 上进一步开发的基础。在这个标准开发的一年中,提交了数百个拉取请求和问题,代表了数千个错误修复、编辑修复和其他改进。此外,还开发了许多软件工具来帮助这一工作,包括 Ecmarkup、Ecmarkdown 和 Grammarkdown。ES2016 还包括对新指数运算符的支持,并向 Array.prototype 添加了一个名为 includes 的新方法。

ECMAScript 2017 引入了异步函数、共享内存和原子操作,以及较小的语言和库增强、错误修复和编辑更新。异步函数通过为返回 promise 的函数提供语法来改善异步编程体验。共享内存和原子操作引入了新的内存模型,允许多代理程序使用原子操作进行通信,确保即使在并行 CPU 上也有明确定义的执行顺序。它还包括 Object 上的新静态方法:Object.valuesObject.entriesObject.getOwnPropertyDescriptors

ECMAScript 2018 通过异步迭代器协议和异步生成器引入了对异步迭代的支持。它还包括四个新的正则表达式功能:dotAll 标志、命名捕获组、Unicode 属性转义和后行断言。最后,它包括对象 rest 和展开属性。

ECMAScript 2019 引入了一些新的内置函数:Array.prototype 上用于扁平化数组的 flatflatMap,用于直接将 Object.entries 的返回值转换为新 Object 的 Object.fromEntries,以及 String.prototype 上的 trimStarttrimEnd,作为广泛实现但非标准的 String.prototype.trimLefttrimRight 内置功能的更好命名替代品。此外,它还包括语法和语义的一些小更新。更新的语法包括可选的 catch 绑定参数,以及允许在字符串字面量中使用 U+2028(行分隔符)和 U+2029(段落分隔符)以与 JSON 保持一致。其他更新包括要求 Array.prototype.sort 为稳定排序,要求 JSON.stringify 无论输入如何都返回格式良好的 UTF-8,以及通过要求它返回相应的原始源文本或标准占位符来澄清 Function.prototype.toString

ECMAScript 2020,第 11 版,为字符串引入了 matchAll 方法,为全局正则表达式生成的所有匹配对象产生一个迭代器import(),一种使用动态说明符异步导入模块的语法;BigInt,用于处理任意精度整数的新数字原始类型;Promise.allSettled,一个不会短路的新 Promise 组合器;globalThis,访问全局 this 值的通用方式;专用的 export * as ns from 'module' 语法,用于在模块内使用;增加了 for-in 枚举顺序的标准化;import.meta,一个在模块中可用的宿主填充对象,可能包含关于模块的上下文信息;以及添加了两个新的语法功能来改善处理"nullish"值(undefinednull)的工作:空值合并,一个值选择运算符;以及可选链,一个属性访问和函数调用运算符,如果要访问/调用的值为 nullish,则会短路。

ECMAScript 2021,第 12 版,为字符串引入了 replaceAll 方法;Promise.any,一个在输入值被满足时短路的 Promise 组合器;AggregateError,一个同时表示多个错误的新 Error 类型;逻辑赋值运算符(??=&&=||=);WeakRef,用于引用目标对象而不阻止其被垃圾回收,以及 FinalizationRegistry,用于管理目标对象被垃圾回收时执行的清理操作的注册和注销;数字字面量的分隔符(1_000);以及 Array.prototype.sort 变得更加精确,减少了导致实现定义排序顺序的情况。

ECMAScript 2022,第 13 版,引入了顶级 await,允许在模块顶级使用该关键字;新的类元素:公共和私有实例字段、公共和私有静态字段、私有实例方法和访问器,以及私有静态方法和访问器;类内的静态块,用于执行每个类的评估初始化;#x in obj 语法,用于测试对象上私有字段的存在;通过 /d 标志的正则表达式匹配索引,提供匹配子字符串的开始和结束索引;Error 对象上的 cause 属性,可用于在错误中记录因果链;字符串、数组和 TypedArrayat 方法,允许相对索引;以及 Object.hasOwnObject.prototype.hasOwnProperty 的便捷替代品。

ECMAScript 2023,第 14 版,在 Array.prototypeTypedArray.prototype 上引入了 toSortedtoReversedwithfindLastfindLastIndex 方法,以及 Array.prototype 上的 toSpliced 方法;增加了对文件开头 #! 注释的支持,以更好地促进可执行的 ECMAScript 文件;并允许在弱集合中使用大多数 Symbol 作为键。

ECMAScript 2024,第 15 版,增加了调整大小和传输 ArrayBuffer 和 SharedArrayBuffer 的功能;增加了新的 RegExp /v 标志,用于创建具有更高级功能的 RegExp 以处理字符串集合;并引入了用于构造 Promise 的 Promise.withResolvers 便捷方法,用于聚合数据的 Object.groupByMap.groupBy 方法,用于异步等待共享内存更改的 Atomics.waitAsync 方法,以及用于检查和确保字符串仅包含格式良好的 Unicode 的 String.prototype.isWellFormedString.prototype.toWellFormed 方法。

ECMAScript 2025,第 16 版,添加了一个新的 Iterator 全局对象,带有相关的静态和原型方法,用于处理迭代器;向 Set.prototype 添加了用于对 Set 执行常见操作的方法;增加了对导入 JSON 模块的支持以及用于声明导入模块属性的语法;添加了用于转义字符串以在正则表达式中安全使用的 RegExp.escape 方法;添加了用于在正则表达式内内联启用和禁用修饰符标志的语法;添加了用于调用可能返回或可能不返回 Promise 的函数并确保结果始终为 PromisePromise.try 方法;并添加了新的 Float16Array TypedArray 类型以及相关的 DataView.prototype.getFloat16DataView.prototype.setFloat16Math.f16round 方法。

代表众多组织的数十名个人在 Ecma TC39 内对本版本和以前版本的开发做出了非常重要的贡献。此外,已经形成了一个充满活力的社区来支持 TC39 的 ECMAScript 工作。这个社区审查了许多草案,提交了数千个错误报告,进行了实现实验,贡献了测试套件,并向全球开发者社区介绍了 ECMAScript。不幸的是,无法识别和承认每个为这一努力做出贡献的个人和组织。

Allen Wirfs-Brock
ECMA-262,项目编辑,第 6 版

Brian Terlson
ECMA-262,项目编辑,第 7 至第 10 版

Jordan Harband
ECMA-262,项目编辑,第 10 至第 12 版

Shu-yu Guo
ECMA-262,项目编辑,第 12 至第 16 版

Michael Ficarra
ECMA-262,项目编辑,第 12 至第 16 版

Kevin Gibbons
ECMA-262,项目编辑,第 12 至第 16 版

1 范围

本标准定义了 ECMAScript 2026 通用编程语言。

2 一致性

ECMAScript 的一致性实现必须提供并支持本规范中描述的所有类型、值、对象、属性、函数以及程序语法和语义。

ECMAScript 的一致性实现必须按照最新版本的 Unicode 标准和 ISO/IEC 10646 来解释源文本输入。

提供应用程序编程接口 (API) 的 ECMAScript 一致性实现,如果该 API 支持需要适应不同人类语言和国家使用的语言和文化约定的程序,则必须实现与本规范兼容的最新版本 ECMA-402 中定义的接口。

ECMAScript 的一致性实现可以提供本规范中描述的类型、值、对象、属性和函数之外的其他类型、值、对象、属性和函数。特别是,ECMAScript 的一致性实现可以为本规范中描述的对象提供本规范中未描述的属性以及这些属性的值。

ECMAScript 的一致性实现可以支持本规范中未描述的程序和正则表达式语法。特别是,ECMAScript 的一致性实现可以支持使用本规范子条款 12.7.2 中注明的任何"未来保留字"的程序语法。

ECMAScript 的一致性实现不得实现子条款 17.1 中列为禁止扩展的任何扩展。

ECMAScript 的一致性实现不得重新定义任何不是实现定义实现近似宿主定义的功能。

ECMAScript 的一致性实现可以选择实现或不实现规范可选子条款。如果实现了任何规范可选行为,则必须实现包含规范可选条款中的所有行为。规范可选条款在本规范中用彩色框中的"规范可选"字样表示,如下所示。

2.1 示例规范可选条款标题

示例条款内容。

ECMAScript 的一致性实现必须实现遗留子条款,除非它们也被标记为规范可选。遗留子条款中指定的所有语言功能和行为都具有一个或多个不良特征。然而,它们在现有应用程序中的持续使用阻止了它们从本规范中被移除。这些功能不被视为核心 ECMAScript 语言的一部分。程序员在编写新的 ECMAScript 代码时不应使用或假设这些功能和行为的存在。

2.2 示例遗留条款标题

示例条款内容。

2.3 示例遗留规范可选条款标题

示例条款内容。

3 规范性引用

以下引用文档对于本文档的应用是必不可少的。对于注明日期的引用,只适用所引用的版本。对于未注明日期的引用,适用引用文档的最新版本(包括任何修订)。

IEEE 754-2019IEEE 浮点运算标准

Unicode 标准。
https://unicode.org/versions/latest

ISO/IEC 10646,信息技术 — 通用多八位编码字符集 (UCS) 加上修订 1:2005、修订 2:2006、修订 3:2008、修订 4:2008,以及其他修订和勘误,或后续版本。

ECMA-402,ECMAScript 国际化 API 规范,特指与本规范版本对应的年度版本。
https://www.ecma-international.org/publications-and-standards/standards/ecma-402/

ECMA-404,JSON 数据交换格式
https://www.ecma-international.org/publications-and-standards/standards/ecma-404/

4 概述

本节包含对 ECMAScript 语言的非规范性概述。

ECMAScript 是一种面向对象的编程语言,用于在宿主环境中执行计算和操作计算对象。这里定义的 ECMAScript 并不打算在计算上自给自足;实际上,本规范中没有外部数据输入或计算结果输出的规定。相反,预期 ECMAScript 程序的计算环境不仅提供本规范中描述的对象和其他设施,还提供某些特定于环境的对象,其描述和行为超出了本规范的范围,除了指出它们可能提供某些可从 ECMAScript 程序访问的属性和某些可调用的函数。

ECMAScript 最初被设计用作脚本语言,但现已广泛用作通用编程语言。脚本语言是一种编程语言,用于操作、自定义和自动化现有系统的设施。在这样的系统中,有用的功能已经通过用户界面可用,脚本语言是将该功能暴露给程序控制的机制。通过这种方式,现有系统被称为提供对象和设施的宿主环境,这完善了脚本语言的功能。脚本语言旨在供专业和非专业程序员使用。

ECMAScript 最初被设计为Web 脚本语言,提供在浏览器中活跃网页并作为基于 Web 的客户端-服务器架构的一部分执行服务器计算的机制。ECMAScript 现在用于为各种宿主环境提供核心脚本功能。因此,核心语言在本文档中独立于任何特定的宿主环境进行规定。

ECMAScript 的使用已经超越了简单的脚本编写,现在用于许多不同环境和规模中编程任务的全谱。随着 ECMAScript 使用的扩展,它提供的功能和设施也在扩展。ECMAScript 现在是一种功能齐全的通用编程语言。

4.1 Web 脚本

Web 浏览器为客户端计算提供 ECMAScript 宿主环境,例如,包括表示窗口、菜单、弹出窗口、对话框、文本区域、锚点、框架、历史记录、cookie 和输入/输出的对象。此外,宿主环境提供了将脚本代码附加到事件(如焦点变化、页面和图像加载、卸载、错误和中止、选择、表单提交和鼠标操作)的方法。脚本代码出现在 HTML 中,显示的页面是用户界面元素和固定及计算文本和图像的组合。脚本代码对用户交互是响应式的,不需要主程序。

Web 服务器为服务器端计算提供不同的宿主环境,包括表示请求、客户端和文件的对象;以及锁定和共享数据的机制。通过同时使用浏览器端和服务器端脚本,可以在客户端和服务器之间分布计算,同时为基于 Web 的应用程序提供自定义用户界面。

每个支持 ECMAScript 的 Web 浏览器和服务器都提供自己的宿主环境,完成 ECMAScript 执行环境。

4.2 宿主和实现

为了帮助将 ECMAScript 集成到宿主环境中,本规范将某些设施(例如,抽象操作)的定义,无论是全部还是部分,推迟到本规范之外的来源。编辑上,本规范区分了以下几种推迟类型。

实现是进一步定义附录 D 中列举的设施或那些标记为实现定义实现近似的设施的外部来源。在非正式使用中,实现指的是具体的产物,如特定的 Web 浏览器。

实现定义设施是将其定义推迟到外部来源而无需进一步限定的设施。本规范不对特定行为提出任何建议,符合规范的实现可以在本规范提出的约束内自由选择任何行为。

实现近似设施是将其定义推迟到外部来源同时推荐理想行为的设施。虽然符合规范的实现可以在本规范提出的约束内自由选择任何行为,但鼓励它们努力接近理想。某些数学运算,如Math.exp,是实现近似的。

宿主是进一步定义附录 D 中列出的设施但不进一步定义其他实现定义实现近似设施的外部来源。在非正式使用中,宿主指的是所有实现的集合,如所有 Web 浏览器的集合,它们通过附录 D 以相同方式与本规范接口。宿主通常是外部规范,如 WHATWG HTML (https://html.spec.whatwg.org/)。换句话说,宿主定义的设施通常在外部规范中进一步定义。

宿主钩子是全部或部分由外部来源定义的抽象操作。所有宿主钩子必须在附录 D 中列出。宿主钩子必须至少符合以下要求:

宿主定义设施是将其定义推迟到外部来源而无需进一步限定并在附录 D 中列出的设施。不是宿主的实现也可以为宿主定义设施提供定义。

宿主环境是对所有宿主定义设施定义的特定选择。宿主环境通常包括允许获取输入和提供输出的对象或函数,作为全局对象宿主定义属性。

本规范遵循始终使用最具体术语的编辑约定。例如,如果一个设施是宿主定义的,它不应该被称为实现定义的。

宿主和实现都可以通过语言类型、规范类型、抽象操作、语法产生式、内置对象和本文定义的内置符号与本规范接口。

4.3 ECMAScript 概述

以下是 ECMAScript 的非正式概述——并非语言的所有部分都被描述。这个概述不是标准本身的一部分。

ECMAScript 是基于对象的:基本语言和宿主设施由对象提供,ECMAScript 程序是一个通信对象的集群。在 ECMAScript 中,对象是零个或多个属性的集合,每个属性都有特性,这些特性决定了每个属性如何使用——例如,当属性的 Writable 特性设置为 false 时,执行的 ECMAScript 代码尝试将不同值赋给该属性的任何尝试都会失败。属性是容纳其他对象、原始值函数的容器。原始值是以下内置类型之一的成员:UndefinedNullBooleanNumberBigIntStringSymbol;对象是内置类型 Object 的成员;函数是可调用对象。通过属性与对象关联的函数称为方法

ECMAScript 定义了一个内置对象集合,完善了 ECMAScript 实体的定义。这些内置对象包括全局对象;对语言的运行时语义基础的对象,包括 ObjectFunctionBooleanSymbol 和各种 Error 对象;表示和操作数值的对象,包括 MathNumberDate;文本处理对象 StringRegExp;作为值的索引集合的对象,包括 Array 和九种不同类型的类型化数组,其元素都有特定的数值数据表示;键值集合,包括 MapSet 对象;支持结构化数据的对象,包括 JSON 对象、ArrayBufferSharedArrayBufferDataView;支持控制抽象的对象,包括生成器函数和 Promise 对象;以及反射对象,包括 ProxyReflect

ECMAScript 还定义了一组内置操作符。ECMAScript 操作符包括各种一元运算、乘性运算符、加性运算符、按位移位运算符、关系运算符、相等运算符、二元按位运算符、二元逻辑运算符、赋值运算符和逗号运算符。

大型 ECMAScript 程序由模块支持,模块允许程序被分为多个语句和声明序列。每个模块明确标识它使用的需要由其他模块提供的声明,以及它的哪些声明可供其他模块使用。

ECMAScript 语法有意类似 Java 语法。ECMAScript 语法被放宽以使其能够作为易于使用的脚本语言。例如,变量不需要声明其类型,类型也不与属性关联,定义的函数不需要在调用之前在文本上出现其声明。

4.3.1 对象

尽管 ECMAScript 包含类定义的语法,但 ECMAScript 对象在根本上不是基于类的,如 C++、Smalltalk 或 Java 中的对象。相反,对象可以通过各种方式创建,包括通过字面量表示法或通过构造函数,构造函数创建对象然后执行代码,通过为其属性分配初始值来初始化全部或部分对象。每个构造函数是具有名为 "prototype" 属性的函数,该属性用于实现基于原型的继承共享属性。对象通过在 new 表达式中使用构造函数创建;例如,new Date(2009, 11) 创建一个新的 Date 对象。在不使用 new 的情况下调用构造函数的后果取决于构造函数。例如,Date() 产生当前日期和时间的字符串表示,而不是对象。

每个由构造函数创建的对象都有一个对其构造函数"prototype" 属性值的隐式引用(称为对象的原型)。此外,原型可能有一个对其原型的非null隐式引用,以此类推;这称为原型链。当对对象中的属性进行引用时,该引用是对原型链中包含该名称属性的第一个对象中该名称的属性的引用。换句话说,首先检查直接提到的对象是否有这样的属性;如果该对象包含命名属性,那就是引用所指的属性;如果该对象不包含命名属性,则接下来检查该对象的原型;以此类推。

图 1:对象/原型关系
一个包含许多框和箭头的图像。

在基于类的面向对象语言中,一般来说,状态由实例承载,方法由类承载,继承只是结构和行为的继承。在 ECMAScript 中,状态和方法由对象承载,而结构、行为和状态都被继承。

所有不直接包含其原型包含的特定属性的对象都共享该属性及其值。图 1 说明了这一点:

CF 是一个构造函数(也是一个对象)。使用 new 表达式创建了五个对象:cf1cf2cf3cf4cf5。这些对象中的每一个都包含名为 "q1""q2" 的属性。虚线表示隐式原型关系;例如,cf3 的原型是 CFp构造函数 CF 本身有两个属性,名为 "P1""P2",这些属性对 CFpcf1cf2cf3cf4cf5 是不可见的。CFp 中名为 "CFP1" 的属性被 cf1cf2cf3cf4cf5(但不是 CF)共享,以及在 CFp 的隐式原型链中找到的不名为 "q1""q2""CFP1" 的任何属性。注意 CFCFp 之间没有隐式原型链接。

与大多数基于类的对象语言不同,可以通过为对象赋值来动态添加属性。也就是说,构造函数不需要命名或为构造对象的所有或任何属性赋值。在上图中,可以通过为 CFp 中的属性赋新值来为 cf1cf2cf3cf4cf5 添加新的共享属性。

虽然 ECMAScript 对象本质上不是基于类的,但基于构造函数函数、原型对象和方法的常见模式定义类似类的抽象通常是方便的。ECMAScript 内置对象本身遵循这样的类似类的模式。从 ECMAScript 2015 开始,ECMAScript 语言包括语法类定义,允许程序员简洁地定义符合内置对象使用的相同类似类抽象模式的对象。

4.3.2 ECMAScript 的严格变体

ECMAScript 语言认识到一些语言用户可能希望限制使用语言中可用的某些功能的可能性。他们可能出于安全考虑、避免他们认为容易出错的功能、获得增强的错误检查或其他他们选择的原因而这样做。为了支持这种可能性,ECMAScript 定义了语言的严格变体。语言的严格变体排除了常规 ECMAScript 语言的一些特定语法和语义功能,并修改了一些功能的详细语义。严格变体还指定了必须通过在非严格形式的语言未指定为错误的情况下抛出错误异常来报告的额外错误条件。

ECMAScript 的严格变体通常被称为语言的严格模式。严格模式的选择和使用以及 ECMAScript 的严格模式语法和语义在个别ECMAScript 源文本单元级别上明确进行,如 11.2.2 中所述。因为严格模式在语法源文本单元级别上被选择,严格模式只施加在这样的源文本单元内具有局部效果的限制。严格模式不限制或修改必须在多个源文本单元中一致运行的 ECMAScript 语义的任何方面。完整的 ECMAScript 程序可以由严格模式和非严格模式ECMAScript 源文本单元组成。在这种情况下,严格模式只在实际执行在严格模式源文本单元中定义的代码时应用。

为了符合本规范,ECMAScript 实现必须实现完整的无限制 ECMAScript 语言和本规范定义的 ECMAScript 语言的严格变体。此外,实现必须支持将无限制和严格模式源文本单元组合到单个复合程序中。

4.4 术语和定义

就本文档而言,以下术语和定义适用。

4.4.1 实现近似

实现近似设施是全部或部分由外部来源定义但在本规范中具有推荐的理想行为的设施

4.4.2 实现定义

实现定义设施是全部或部分由本规范外部来源定义的设施

4.4.3 宿主定义

实现定义相同

编辑上,见条款 4.2

4.4.4 类型

如条款 6 中定义的数据值集合

4.4.5 原始值

Undefined、Null、Boolean、Number、BigInt、Symbol 或 String 类型之一的成员,如条款 6 中定义

原始值是在语言实现的最低级别直接表示的数据。

4.4.6 对象

Object 类型的成员

对象是属性的集合,并且有一个原型对象。原型可能是 null

4.4.7 构造函数

创建和初始化对象的函数对象

构造函数"prototype" 属性的值是用于实现继承和共享属性的原型对象。

4.4.8 原型

为其他对象提供共享属性的对象

构造函数创建对象时,该对象隐式引用构造函数"prototype" 属性以解决属性引用。构造函数"prototype" 属性可以通过程序表达式 constructor.prototype 引用,添加到对象原型的属性通过继承被所有共享该原型的对象共享。或者,可以使用 Object.create 内置函数创建具有明确指定原型的新对象。

4.4.9 普通对象

对于所有对象必须支持的基本内部方法具有默认行为的对象

4.4.10 异质对象

对于一个或多个基本内部方法没有默认行为的对象

任何不是普通对象的对象都是异质对象

4.4.11 标准对象

语义由本规范定义的对象

4.4.12 内置对象

由 ECMAScript 实现指定和提供的对象

标准内置对象在本规范中定义。ECMAScript 实现可以指定和提供本规范中未描述的其他类型的内置对象。

4.4.13 undefined 值

在变量未被赋值时使用的原始值

4.4.14 Undefined 类型

唯一值为 undefined 值的类型

4.4.15 null 值

表示故意缺少任何对象值的原始值

4.4.16 Null 类型

唯一值为 null 值的类型

4.4.17 Boolean 值

Boolean 类型的成员

只有两个 Boolean 值,truefalse

4.4.18 Boolean 类型

由原始值 truefalse 组成的类型

4.4.19 Boolean 对象

Object 类型的成员,是标准内置 Boolean 构造函数的实例

Boolean 对象通过在 new 表达式中使用 Boolean 构造函数创建,提供 Boolean 值作为参数。生成的对象有一个内部槽,其值是 Boolean 值。Boolean 对象可以被强制转换为 Boolean 值。

4.4.20 String 值

原始值,是零个或多个 16 位无符号整数值的有限有序序列

String 值是String 类型的成员。序列中的每个整数值通常表示 UTF-16 文本的单个 16 位单元。但是,ECMAScript 对值没有任何限制或要求,除了它们必须是 16 位无符号整数

4.4.21 String 类型

所有可能 String 值的集合

4.4.22 String 对象

Object 类型的成员,是标准内置 String 构造函数的实例

String 对象通过在 new 表达式中使用 String 构造函数创建,提供 String 值作为参数。生成的对象有一个内部槽,其值是 String 值。String 对象可以通过调用 String 构造函数作为函数被强制转换为 String 值(22.1.1.1)。

4.4.23 Number 值

对应于双精度 64 位二进制格式 IEEE 754-2019 值的原始值

Number 值是Number 类型的成员,是数字的直接表示。

4.4.24 Number 类型

所有可能 Number 值的集合,包括 NaN("非数字")、+∞𝔽(正无穷大)和 -∞𝔽(负无穷大)

4.4.25 Number 对象

Object 类型的成员,是标准内置 Number 构造函数的实例

Number 对象通过在 new 表达式中使用 Number 构造函数创建,提供 Number 值作为参数。生成的对象有一个内部槽,其值是 Number 值。Number 对象可以通过调用 Number 构造函数作为函数被强制转换为 Number 值(21.1.1.1)。

4.4.26 Infinity

正无限 Number 值的 Number 值

4.4.27 NaN

IEEE 754-2019 NaN("非数字")值的 Number 值

4.4.28 BigInt 值

对应于任意精度整数值的原始值

4.4.29 BigInt 类型

所有可能 BigInt 值的集合

4.4.30 BigInt 对象

Object 类型的成员,是标准内置 BigInt 构造函数的实例

4.4.31 Symbol 值

表示唯一、非 String 对象属性键的原始值

4.4.32 Symbol 类型

所有可能 Symbol 值的集合

4.4.33 Symbol 对象

Object 类型的成员,是标准内置 Symbol 构造函数的实例

4.4.34 函数

Object 类型的成员,可以作为子程序调用

除了其属性外,函数包含可执行代码和状态,这些决定了调用时的行为。函数的代码可能用 ECMAScript 编写,也可能不是。

4.4.35 内置函数

是函数的内置对象

内置函数的例子包括 parseIntMath.exp宿主或实现可能提供本规范中未描述的其他内置函数。

4.4.36 内置构造函数

构造函数的内置函数

内置构造函数的例子包括 ObjectFunction宿主或实现可能提供本规范中未描述的其他内置构造函数

4.4.37 属性

对象的一部分,将键(String 值或 Symbol 值)与值关联

根据属性的形式,值可以直接表示为数据值(原始值、对象或函数对象)或间接通过一对访问器函数表示。

4.4.38 方法

作为属性值的函数

当函数作为对象的方法调用时,对象作为其 this 值传递给函数。

4.4.39 内置方法

是内置函数的方法

标准内置方法在本规范中定义。宿主或实现可能提供本规范中未描述的其他内置方法。

4.4.40 特性

定义属性某些特征的内部值

4.4.41 自有属性

直接包含在其对象中的属性

4.4.42 继承属性

对象的属性,不是自有属性但是对象原型的属性(自有或继承)

4.5 本规范的组织结构

本规范的其余部分组织如下:

章节 5 定义了整个规范中使用的记号约定。

章节 610 定义了 ECMAScript 程序运行的执行环境。

章节 1117 定义了实际的 ECMAScript 编程语言,包括其语法编码和所有语言功能的执行语义。

章节 1828 定义了 ECMAScript 标准库。它们包括所有标准对象的定义,这些对象可供 ECMAScript 程序在执行时使用。

章节 29 描述了对 SharedArrayBuffer 支持的内存的访问的内存一致性模型以及 Atomics 对象的方法。

5 记号约定

5.1 语法和词法文法

5.1.1 上下文无关文法

上下文无关文法由若干产生式组成。每个产生式的左侧有一个称为非终结符的抽象符号,右侧是零个或多个非终结符和终结符符号的序列。对于每个文法,终结符都从指定的字母表中选取。

链式产生式是在其右侧恰好有一个非终结符号以及零个或多个终结符的产生式。

从一个由单一特殊非终结符组成的句子开始,称为目标符号,给定的上下文无关文法指定一种语言,即,通过反复将序列中的任何非终结符替换为以该非终结符作为左侧的产生式的右侧,可能产生的终结符序列的(可能无限的)集合。

5.1.2 词法和 RegExp 文法

ECMAScript 的词法文法第 12 条中给出。该文法以符合 11.1 中定义的 SourceCharacter 规则的 Unicode 码点作为其终结符。它定义了一组产生式,从目标符号 InputElementDivInputElementTemplateTailInputElementRegExpInputElementRegExpOrTemplateTailInputElementHashbangOrRegExp 开始,这些产生式描述了此类码点序列如何转换为输入元素序列。

除空白和注释之外的输入元素构成了 ECMAScript 句法文法的终结符,并被称为 ECMAScript 标记。这些标记是 ECMAScript 语言的保留字、标识符、字面量和标点符号。此外,行终止符虽然不被视作标记,但也成为输入元素流的一部分,并指导自动分号插入(12.10)的过程。简单的空白和单行注释会被丢弃,不会出现在句法文法的输入元素流中。如果 MultiLineComment(即形式为 /**/ 的注释,无论其是否跨越多行)不包含行终止符,则同样会被简单丢弃;但如果 MultiLineComment 包含一个或多个行终止符,则它会被替换为单个行终止符,该行终止符成为句法文法输入元素流的一部分。

ECMAScript 的 RegExp 文法在章节 22.2.1 中给出。此文法的终结符也是由 SourceCharacter 定义的代码点。它定义了一组产生式,从目标符号 Pattern 开始,描述如何将代码点序列转换为正则表达式模式。

词法文法和 RegExp 文法的产生式以两个冒号"::"作为分隔标点符号来区分。词法文法和 RegExp 文法共享一些产生式。

5.1.3 数值字符串文法

数值字符串文法出现在章节 7.1.4.1 中。它以 SourceCharacter 作为终结符,用于从目标符号 StringNumericLiteral 开始将字符串转换为数值(这与数值字面量的词法文法相似但不同)。

数值字符串文法的产生式以三个冒号":::"作为标点符号来区分,从不用于解析源文本。

5.1.4 语法文法

ECMAScript 的语法文法在章节 1316 中给出。此文法以词法文法定义的 ECMAScript 标记作为终结符(5.1.2)。它定义了一组产生式,从两个可选的目标符号 ScriptModule 开始,描述标记序列如何构成语法上正确的 ECMAScript 程序独立组件。

当代码点流要被解析为 ECMAScript ScriptModule 时,首先通过反复应用词法文法将其转换为输入元素流;然后通过单次应用语法文法解析此输入元素流。如果输入元素流中的标记无法解析为目标非终结符(ScriptModule)的单个实例且没有剩余标记,则输入流在语法上是错误的。

当解析成功时,它构造一个解析树,这是一个根树结构,其中每个节点都是一个解析节点。每个解析节点是文法中符号的一个实例;它表示可以从该符号派生的源文本范围。表示整个源文本的解析树根节点是解析的目标符号的实例。当解析节点是非终结符的实例时,它也是以该非终结符作为左侧的某个产生式的实例。此外,它有零个或多个子节点,对应产生式右侧的每个符号:每个子节点都是对应符号实例的解析节点。

为每次解析器调用实例化新的解析节点,即使是相同源文本的解析也从不重用。当且仅当解析节点表示相同的源文本范围、是相同文法符号的实例且来自相同的解析器调用时,才被认为是同一个解析节点

注 1

多次解析相同的字符串将导致不同的解析节点。例如,考虑:

let str = "1 + 1;";
eval(str);
eval(str);

每次调用 eval 都将 str 的值转换为 ECMAScript 源文本并执行独立的解析,创建自己独立的解析节点树。即使每次解析都操作从相同字符串值派生的源文本,这些树也是不同的。

注 2
解析节点是规范产物,实现不需要使用类似的数据结构。

语法文法的产生式以仅一个冒号":"作为标点符号来区分。

章节 1316 中呈现的语法文法并不完整地说明哪些标记序列被接受为正确的 ECMAScript ScriptModule。某些额外的标记序列也被接受,即那些如果只在序列的某些位置(如行结束符字符之前)添加分号就会被文法描述的序列。此外,如果行结束符字符出现在某些"尴尬"位置,那么文法描述的某些标记序列不被认为是可接受的。

在某些情况下,为了避免歧义,语法文法使用广义产生式,允许不构成有效 ECMAScript ScriptModule 的标记序列。例如,这种技术用于对象字面量和对象解构模式。在这种情况下,提供更严格的补充文法来进一步限制可接受的标记序列。通常,早期错误规则会声明,在某些上下文中,"P 必须覆盖一个 N",其中 P 是解析节点(广义产生式的实例),N 是补充文法中的非终结符。这意味着:

  1. 最初由 P 匹配的标记序列使用 N 作为目标符号重新解析。如果 N 接受文法参数,则设置为最初解析 P 时使用的相同值。
  2. 如果标记序列可以解析为 N 的单个实例且没有剩余标记,则:
    1. 我们将 N 的该实例(对于给定的 P 是唯一的解析节点)称为"被 P 覆盖N"。
    2. N 及其派生产生式的所有早期错误规则也适用于被 P 覆盖的 N
  3. 否则(如果解析失败),这是早期语法错误。

5.1.5 文法符号

5.1.5.1 终结符号

在 ECMAScript 文法中,一些终结符号以 固定宽度 字体显示。 这些符号必须在源文本中完全按照所写的方式出现。以这种方式指定的所有终结符号代码点 都应理解为来自基本拉丁块的适当 Unicode 代码点,而不是来自其他 Unicode 范围的任何类似代码点。 终结符号中的代码点不能用 \ UnicodeEscapeSequence 表示。

在终结符号为单个 Unicode 代码点的文法中(即词法、正则表达式和数字字符串文法), 产生式中出现的多个连续固定宽度代码点是相同代码点序列的简写, 写作独立的终结符号。

例如,产生式:

HexIntegerLiteral :: 0x HexDigits

是以下的简写:

HexIntegerLiteral :: 0 x HexDigits

相比之下,在语法文法中,连续的固定宽度代码点是单个终结符号。

终结符号有另外两种形式:

  • 在词法和正则表达式文法中,没有常规打印表示的 Unicode 代码点 以 "<ABBREV>" 的形式显示,其中 "ABBREV" 是代码点或代码点集合的助记符。 这些形式在 Unicode 格式控制字符空白符行终止符 中定义。
  • 在语法文法中,某些终结符号(例如 IdentifierNameRegularExpressionLiteral) 以斜体显示,因为它们引用词法文法中的同名非终结符。

5.1.5.2 非终结符号和产生式

非终结符号以 斜体 显示。非终结符的定义(也称为"产生式") 由要定义的非终结符的名称后跟一个或多个冒号引入。(冒号的数量表示产生式属于哪个文法。) 然后在后续行中跟随非终结符的一个或多个可选右侧。例如,语法定义:

WhileStatement : while ( Expression ) Statement

表示非终结符 WhileStatement 代表 token while,后跟左括号 token,后跟 Expression,后跟右 括号 token,后跟 StatementExpressionStatement 的出现本身就是 非终结符。另一个例子,语法定义:

ArgumentList : AssignmentExpression ArgumentList , AssignmentExpression

表示 ArgumentList 可以代表 单个 AssignmentExpression,或者 ArgumentList 后跟逗号,后跟 AssignmentExpression。这个 ArgumentList 的定义是递归的, 即它是根据自身定义的。结果是 ArgumentList 可以包含任意 正数个参数,用逗号分隔,其中每个参数表达式都是 AssignmentExpression。这种非终结符的递归定义很常见。

5.1.5.3 可选符号

下标后缀 "opt" 可能出现在终结符或非终结符之后,表示可选符号。 包含可选符号的选择实际上指定了两个右侧,一个省略可选元素,一个包含它。这意味着:

VariableDeclaration : BindingIdentifier Initializeropt

是以下的便利缩写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer

并且:

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

是以下的便利缩写:

ForStatement : for ( LexicalDeclaration ; Expressionopt ) Statement for ( LexicalDeclaration Expression ; Expressionopt ) Statement

这又是以下的缩写:

ForStatement : for ( LexicalDeclaration ; ) Statement for ( LexicalDeclaration ; Expression ) Statement for ( LexicalDeclaration Expression ; ) Statement for ( LexicalDeclaration Expression ; Expression ) Statement

所以,在这个例子中,非终结符 ForStatement 实际上有 四个可选的右侧。

5.1.5.4 文法参数

产生式可以通过下标注释的形式 "[parameters]" 进行参数化, 该注释可以作为产生式定义的非终结符号的后缀出现。"parameters" 可以是单个名称 或用逗号分隔的名称列表。参数化产生式是一组产生式的简写, 定义了参数名称的所有组合,在下划线前面,附加到参数化非终结符号。这意味着:

StatementList[Return] : ReturnStatement ExpressionStatement

是以下的便利缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return, In] : ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement StatementList_In : ReturnStatement ExpressionStatement StatementList_Return_In : ReturnStatement ExpressionStatement

多个参数产生组合数量的产生式,并非所有这些产生式都必须在完整文法中引用。

产生式右侧的非终结符引用也可以参数化。例如:

StatementList : ReturnStatement ExpressionStatement[+In]

等价于说:

StatementList : ReturnStatement ExpressionStatement_In

并且:

StatementList : ReturnStatement ExpressionStatement[~In]

等价于:

StatementList : ReturnStatement ExpressionStatement

非终结符引用可以同时具有参数列表和 "opt" 后缀。例如:

VariableDeclaration : BindingIdentifier Initializer[+In]opt

是以下的缩写:

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer_In

在右侧非终结符引用中,使用 "?" 作为参数名称的前缀 使该参数值依赖于当前产生式左侧符号引用中该参数名称的出现。例如:

VariableDeclaration[In] : BindingIdentifier Initializer[?In]

是以下的缩写:

VariableDeclaration : BindingIdentifier Initializer VariableDeclaration_In : BindingIdentifier Initializer_In

如果右侧选择以 "[+parameter]" 为前缀,那么该选择只有在引用产生式的非终结符号时使用了命名参数才可用。 如果右侧选择以 "[~parameter]" 为前缀,那么该选择只有在引用产生式的非终结符号时 没有 使用命名参数才可用。这意味着:

StatementList[Return] : [+Return] ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

并且:

StatementList[Return] : [~Return] ReturnStatement ExpressionStatement

是以下的缩写:

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ExpressionStatement

5.1.5.5 one of

当单词 "one of" 跟在文法定义中的冒号后面时,它们表示后续行中的每个终结符号 都是一个可选定义。例如,ECMAScript 的词法文法包含产生式:

NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9

这只是以下的便利缩写:

NonZeroDigit :: 1 2 3 4 5 6 7 8 9

5.1.5.6 [empty]

如果短语 "[empty]" 作为产生式的右侧出现,它表示产生式的右侧不包含终结符或非终结符。

5.1.5.7 前瞻限制

如果短语 "[lookahead = seq]" 出现在产生式的右侧, 它表示只有当标记序列 seq 是紧随其后的输入标记序列的前缀时,才能使用该产生式。类似地,"[lookahead ∈ set]"(其中 set 是标记序列的 有限非空集合)表示只有当 set 中的某个元素是紧随其后的标记序列的前缀时,才能使用该产生式。为了方便起见,集合也可以写作非终结符,在这种情况下,它代表该非终结符可以展开为的所有标记序列的集合。如果非终结符能够展开为无限多个不同的标记序列,则认为这是编辑错误。

这些条件可以被否定。"[lookahead ≠ seq]" 表示只有当 seq 不是紧随其后的输入标记序列的前缀时,才能使用包含的产生式,而 "[lookahead ∉ set]" 表示只有当 set没有元素是紧随其后的标记序列的前缀时,才能使用该产生式。

作为示例,给定定义:

DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 DecimalDigits :: DecimalDigit DecimalDigits DecimalDigit

定义:

LookaheadExample :: n [lookahead ∉ { 1, 3, 5, 7, 9 }] DecimalDigits DecimalDigit [lookahead ∉ DecimalDigit]

匹配字母 n 后跟一个或多个十进制数字(其中第一个数字是偶数),或者一个十进制数字后面不跟另一个十进制数字。

注意,当这些短语在语法文法中使用时,可能无法明确地识别紧随其后的标记序列,因为确定后续标记需要知道在后续位置使用哪个词法目标符号。因此,当这些在语法文法中使用时,如果标记序列 seq 出现在前瞻限制中(包括作为序列集合的一部分),并且词法目标符号的选择可能改变 seq 是否为结果标记序列的前缀,则认为这是编辑错误。

5.1.5.8 [no LineTerminator here]

如果短语 "[no LineTerminator here]" 出现在语法文法产生式的右侧,它表示该产生式是受限产生式:如果在输入流的指定位置出现 LineTerminator,则不能使用该产生式。例如,产生式:

ThrowStatement : throw [no LineTerminator here] Expression ;

表示如果在脚本的 throw 标记和 Expression 之间出现 LineTerminator,则不能使用该产生式。

除非受限产生式禁止出现 LineTerminator,否则在输入元素流中任意两个连续标记之间可以出现任意数量的 LineTerminator,而不会影响脚本的语法可接受性。

5.1.5.9 but not

产生式的右侧可以通过使用短语 "but not" 然后指出要排除的展开来指定某些展开是不被允许的。例如,产生式:

Identifier :: IdentifierName but not ReservedWord

意味着非终结符 Identifier 可以被任何能够替换 IdentifierName 的代码点序列所替换,但前提是相同的代码点序列不能替换 ReservedWord

5.1.5.10 描述性短语

最后,少数非终结符通过无衬线字体的描述性短语来描述,这是在列出所有选择不切实际的情况下:

SourceCharacter :: any Unicode code point

5.2 算法约定

本规范通常使用编号列表来指定算法中的步骤。这些算法用于精确指定 ECMAScript 语言构造所需的语义。这些算法并非旨在暗示使用任何特定的实现技术。实际上,可能存在更有效的算法来实现给定的特性。

算法可以使用有序的、逗号分隔的别名序列进行显式参数化,这些别名可以在算法步骤中用于引用在该位置传入的参数。可选参数用方括号([ , name ])表示,在算法步骤中与必需参数没有区别。剩余参数可以出现在参数列表的末尾,用前导省略号(, ...name)表示。剩余参数将捕获在必需参数和可选参数之后提供的所有参数到一个 列表中。如果没有此类附加参数,则该 列表为空。

算法步骤可以细分为顺序的子步骤。子步骤是缩进的,并且它们本身可以进一步划分为缩进的子步骤。使用大纲编号约定来标识子步骤,第一级子步骤用小写字母标记,第二级子步骤用小写罗马数字标记。如果需要三个以上的级别,则这些规则会重复,第四级使用数字标签。例如:

  1. 顶层步骤
    1. 子步骤。
    2. 子步骤。
      1. 子子步骤。
        1. 子子子步骤
          1. 子子子子步骤
            1. 子子子子子步骤

一个步骤或子步骤可以写成一个“if”谓词,该谓词对其子步骤进行条件限制。在这种情况下,仅当谓词为真时才应用子步骤。如果一个步骤或子步骤以单词“else”开头,则它是一个谓词,该谓词是同一级别上在前的“if”谓词步骤的否定。

一个步骤可以指定其子步骤的迭代应用。

以“断言:”开头的步骤断言其算法的不变条件。此类断言用于明确算法中否则将是隐式的不变量。此类断言不增加额外的语义要求,因此实现无需检查。它们仅用于阐明算法。

算法步骤可以使用“令 xsomeValue”的形式为任何值声明命名别名。这些别名是引用式的,即 xsomeValue 都引用相同的基础数据,对其中任何一个的修改对两者都可见。希望避免这种引用式行为的算法步骤应显式复制右侧的值:“令 xsomeValue 的副本”会创建 someValue 的浅拷贝。

一旦声明,别名就可以在任何后续步骤中引用,并且不得在别名声明之前的步骤中引用。可以使用“将 x 设置为 someOtherValue”的形式修改别名。

5.2.1 抽象操作

为了便于在规范的多个部分中使用,一些算法(称为抽象操作)被命名并以参数化函数形式编写,以便可以从其他算法中按名称引用它们。抽象操作通常使用函数应用样式(如 OperationName(arg1, arg2))进行引用。一些抽象操作被视为类规范抽象的多态分派方法。此类方法式抽象操作通常使用方法应用样式(如 someValue.OperationName(arg1, arg2))进行引用。

5.2.2 语法导向操作

语法导向操作是一种命名操作,其定义由算法组成,每个算法都与 ECMAScript 语法中的一个或多个产生式相关联。具有多个备选定义的产生式通常会为每个备选方案提供一个不同的算法。当算法与语法产生式相关联时,它可以像引用算法参数一样引用产生式备选方案的终结符和非终结符。以这种方式使用时,非终结符指的是解析源文本时匹配的实际备选定义。语法产生式或由其派生的 解析节点 匹配的源文本是源文本中从参与匹配的第一个终结符的开头开始到参与匹配的最后一个终结符的结尾结束的部分。

当算法与产生式备选方案相关联时,该备选方案通常不带任何“[ ]”语法注释。此类注释仅影响备选方案的语法识别,对备选方案的相关语义没有影响。

语法导向操作通过使用以下算法中的步骤 134 的约定,使用解析节点以及可选的其他参数来调用:

  1. statusSomeNonTerminal 的 SyntaxDirectedOperation。
  2. someParseNode 为某个源文本的解析结果。
  3. 执行 someParseNode 的 SyntaxDirectedOperation。
  4. 执行 someParseNode 的 SyntaxDirectedOperation,参数为 "value"

除非另有明确规定,否则所有 链式产生式对于可能应用于该产生式左侧非终结符的每个操作都有一个隐式定义。该隐式定义只是将相同的操作(以及任何参数)重新应用于链式产生式的唯一右侧非终结符,然后返回结果。例如,假设某个算法有一个步骤的形式为:“返回 求值”,并且有一个产生式:

: { 语句列表 }

但是 求值 操作没有将算法与该产生式关联起来。在这种情况下,求值 操作隐式地包含一个形式如下的关联:

运行时语义:求值

: { 语句列表 }
  1. 返回 语句列表求值

5.2.3 运行时语义

指定必须在运行时调用的语义的算法称为运行时语义。运行时语义由 抽象操作语法导向操作定义。

5.2.3.1 Completion ( completionRecord )

抽象操作 Completion 接受参数 completionRecord(一个 完成记录)并返回一个 完成记录。它用于强调正在返回一个 完成记录。调用时它执行以下步骤:

  1. 断言completionRecord 是一个 完成记录
  2. 返回 completionRecord

5.2.3.2 抛出异常

算法步骤中说要抛出异常,例如:

  1. 抛出一个 TypeError 异常。

与以下含义相同:

  1. 返回 ThrowCompletion(一个新创建的 TypeError 对象)。

5.2.3.3 ReturnIfAbrupt

算法步骤中说或等效于:

  1. ReturnIfAbrupt(argument)。

与以下含义相同:

  1. 断言argument 是一个 完成记录
  2. 如果 argument 是一个 突然完成,则返回 Completion(argument)。
  3. 否则,将 argument 设置为 argument.[[Value]]

算法步骤中说或等效于:

  1. ReturnIfAbrupt(AbstractOperation())。

与以下含义相同:

  1. hygienicTemp 为 AbstractOperation()。
  2. 断言hygienicTemp 是一个 完成记录
  3. 如果 hygienicTemp 是一个 突然完成,则返回 Completion(hygienicTemp)。
  4. 否则,将 hygienicTemp 设置为 hygienicTemp.[[Value]]

其中 hygienicTemp 是临时的,并且仅在与 ReturnIfAbrupt 相关的步骤中可见。

算法步骤中说或等效于:

  1. result 为 AbstractOperation(ReturnIfAbrupt(argument))。

与以下含义相同:

  1. 断言argument 是一个 完成记录
  2. 如果 argument 是一个 突然完成,则返回 Completion(argument)。
  3. 否则,将 argument 设置为 argument.[[Value]]
  4. result 为 AbstractOperation(argument)。

5.2.3.4 ReturnIfAbrupt 简写

? 为前缀的 抽象操作语法导向操作的调用表示应将 ReturnIfAbrupt 应用于结果 完成记录。例如,步骤:

  1. ? OperationName()。

等效于以下步骤:

  1. ReturnIfAbrupt(OperationName())。

类似地,对于方法应用样式,步骤:

  1. someValue.OperationName()。

等效于:

  1. ReturnIfAbrupt(someValue.OperationName())。

类似地,前缀 ! 用于指示以下抽象操作或 语法导向操作的调用永远不会返回 突然完成,并且应使用结果 完成记录[[Value]] 字段代替操作的返回值。例如,步骤:

  1. val 为 ! OperationName()。

等效于以下步骤:

  1. val 为 OperationName()。
  2. 断言val 是一个 正常完成
  3. val 设置为 val.[[Value]]

语法导向操作运行时语义通过在操作调用前放置 !? 来使用此简写:

  1. 执行 ! NonTerminal 的 SyntaxDirectedOperation。

5.2.3.5 隐式正常完成

在声明返回 完成记录抽象操作内的算法中,以及在所有内置函数中,返回值首先传递给 NormalCompletion,并使用其结果。此规则不适用于 Completion 算法内,或者当返回的值在该步骤中明确标记为 完成记录时;这些情况是:

如果通过任何其他方式从此类抽象操作返回 完成记录,则属于编辑错误。例如,在这些 抽象操作中,

  1. 返回 true

与以下任何一种含义相同:

  1. 返回 NormalCompletion(true)。

  1. completionNormalCompletion(true)。
  2. 返回 Completion(completion)。

  1. 返回 完成记录 { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }。

请注意,通过 ReturnIfAbrupt 展开,以下示例是允许的,因为在展开的步骤中,应用 Completion 的结果在突然情况下直接返回,而隐式的 NormalCompletion 应用在正常情况下解包后发生。

  1. 返回 ? completion

以下示例将是编辑错误,因为正在返回一个 完成记录,而没有在该步骤中进行注释。

  1. completionNormalCompletion(true)。
  2. 返回 completion

5.2.4 静态语义

上下文无关文法不足以表达所有规则,这些规则定义输入元素流是否形成一个有效的、可以求值的 ECMAScript 脚本模块。在某些情况下,需要额外的规则,这些规则可以使用 ECMAScript 算法约定或散文要求来表达。此类规则始终与语法的产生式相关联,并称为产生式的静态语义

静态语义规则具有名称,并且通常使用算法定义。命名的静态语义规则与语法产生式相关联,具有多个备选定义的产生式通常会为每个备选方案的每个适用的命名静态语义规则提供一个不同的算法。

一种特殊的静态语义规则是早期错误规则早期错误规则定义了与特定语法产生式相关的早期错误条件(参见第 17 条)。本规范的算法中并未显式调用大多数早期错误规则的求值。一致性实现必须在首次求值 脚本模块之前,验证用于解析该 脚本模块的产生式的所有早期错误规则。如果违反了任何早期错误规则,则该 脚本模块无效且无法求值

5.2.5 数学运算

本规范引用以下类型的数值:

  • 数学值:任意实数,用作默认数值类型。
  • 扩展数学值数学值以及 +∞ 和 -∞。
  • 数字IEEE 754-2019 binary64(双精度浮点)值。
  • BigIntsECMAScript 语言值,以一一对应的方式表示任意整数

在本规范的语言中,使用下标后缀来区分不同数值种类的数值。下标 𝔽 指的是数字,下标 指的是 BigInts。没有下标后缀的数值指的是数学值。本规范以十进制表示大多数数值;它也使用 0x 后跟数字 0-9 或 A-F 的形式的数值作为十六进制值。

通常,当本规范引用一个数值时,例如在短语“y 的长度”或“由四个十六进制数字表示的整数...”中,而没有明确指定数值种类时,该短语指的是一个数学值。引用数字或 BigInt 值的短语会明确注释;例如,“...中代码点数量的数字值”或“...的BigInt 值”。

当本规范中使用术语整数时,它指的是一个数学值,该值在整数集合中,除非另有说明。当本规范中使用术语整数数字值时,它指的是一个有限数字值,其数学值整数集合中。

诸如 +、×、= 和 ≥ 之类的数值运算符指的是由操作数类型决定的那些运算。当应用于数学值时,这些运算符指的是通常的数学运算。当应用于扩展数学值时,这些运算符指的是扩展实数上的通常数学运算;不确定形式未定义,在本规范中使用它们应被视为编辑错误。当应用于数字时,这些运算符指的是IEEE 754-2019中的相关运算。当应用于 BigInts 时,这些运算符指的是应用于 BigInt 的数学值的通常数学运算。应用于混合类型操作数(例如数字和数学值)的数值运算符未定义,在本规范中应被视为编辑错误。

数学值与数字或 BigInts 之间的转换在本文档中始终是显式的。从数学值扩展数学值 x 到数字的转换表示为“x数字值”或 𝔽(x),并在 6.1.6.1 中定义。从整数 x 到 BigInt 的转换表示为“xBigInt 值”或 ℤ(x)。从数字或 BigInt x数学值的转换表示为“x数学值”,或 ℝ(x)+0𝔽-0𝔽数学值数学值 0。非有限值的数学值未定义。x扩展数学值对于有限值是 x数学值,对于 +∞𝔽-∞𝔽 分别是 +∞ 和 -∞;对于 NaN 未定义。

数学函数 abs(x) 产生 x 的绝对值,如果 x < 0 则为 -x,否则为 x 本身。

数学函数 min(x1, x2, … , xN) 产生 x1xN 中数学上最小的值。数学函数 max(x1, x2, ..., xN) 产生 x1xN 中数学上最大的值。这些数学函数的定义域和值域是扩展数学值

符号“xy”(y 必须是有限且非零)计算一个与 y 同符号(或为零)的值 k,使得 abs(k) < abs(y) 且 x - k = q × y 对于某个整数 q 成立。

短语“将 x 限制lowerupper 之间”的结果(其中 x 是一个扩展数学值lowerupper数学值lowerupper)是:如果 x < lower 则为 lower,如果 x > upper 则为 upper,否则为 x

数学函数 floor(x) 产生不大于 x 的最大整数(最接近 +∞)。

注意

floor(x) = x - (x 1)

数学函数 truncate(x) 通过向零取整来移除 x 的小数部分,如果 x < 0 则产生 -floor(-x),否则产生 floor(x)

数学函数 minmaxabsfloortruncate 未针对数字和 BigInts 定义,任何使用非数学值参数的这些方法的用法在本规范中都应视为编辑错误。

从下界 a 到上界 b区间是一个可能是无限的、可能是空的、相同数值类型的数值集合。每个界限将被描述为包含的或排除的,但不能两者都是。有四种区间,如下所示:

  • a(包含)到 b(包含)的区间,也称为从 ab闭区间,包括所有相同数值类型的数值 x,使得 axb,且不包括其他值。
  • a(包含)到 b(排除)的区间包括所有相同数值类型的数值 x,使得 ax < b,且不包括其他值。
  • a(排除)到 b(包含)的区间包括所有相同数值类型的数值 x,使得 a < xb,且不包括其他值。
  • a(排除)到 b(排除)的区间包括所有相同数值类型的数值 x,使得 a < x < b,且不包括其他值。

例如,从 1(包含)到 2(排除)的区间包含所有介于 1 和 2 之间的数学值,包括 1 但不包括 2。为了定义区间,-0𝔽 < +0𝔽,因此,例如,下界为 +0𝔽闭区间包括 +0𝔽 但不包括 -0𝔽NaN 从不包含在区间中。

5.2.6 值表示法

在本规范中,ECMAScript 语言值粗体显示。示例包括 nulltrue"hello"。这些与 ECMAScript 源文本(如 Function.prototype.applylet n = 42;)相区别。

5.2.7 同一性

在本规范中,规范值和 ECMAScript 语言值都会进行相等性比较。在比较相等性时,值分为两类。无同一性的值如果其所有固有特征(例如整数的大小或序列的长度)都相同,则与其他无同一性的值相等。无同一性的值可以通过完全描述其特征来体现,而无需事先引用。相比之下,每个有同一性的值都是唯一的,因此只等于其自身。有同一性的值类似于无同一性的值,但具有一个额外的、不可猜测的、不可改变的、普遍唯一的特征,称为同一性。对现有有同一性的值的引用不能简单地通过描述它们来体现,因为同一性本身是不可描述的;相反,对这些值的引用必须从一个地方显式传递到另一个地方。一些有同一性的值是可变的,因此可以就地更改其特征(除了其同一性),从而使该值的所有持有者都观察到新的特征。无同一性的值永远不等于有同一性的值。

从本规范的角度来看,“是”用于比较两个值的相等性,如“如果 booltrue,则 ...”,而“包含”用于使用相等性比较在列表中搜索值,如“如果 list 包含一个 记录 r 使得 r.[[Foo]]true,则 ...”。值的规范同一性决定了这些比较的结果,并且在本规范中是公理性的。

从 ECMAScript 语言的角度来看,语言值使用 SameValue 抽象操作及其传递调用的 抽象操作进行相等性比较。这些比较抽象操作的算法确定了 ECMAScript 语言值语言同一性

对于规范值,无规范同一性的值的示例包括但不限于:数学值扩展数学值ECMAScript 源文本代理对指令序言等;UTF-16 代码单元;Unicode 码点;枚举抽象操作,包括语法导向操作宿主钩子等;以及有序对。有规范同一性的规范值的示例包括但不限于:任何类型的记录,包括属性描述符私有元素等;解析节点列表集合关系抽象闭包数据块私有名称执行上下文执行上下文栈代理标识符;以及WaiterList 记录

对于所有 ECMAScript 语言值,规范同一性与语言同一性一致,但由 Symbol.for 产生的 Symbol 值除外。无规范同一性和无语言同一性的 ECMAScript 语言值undefinednull布尔值字符串数字BigInts。有规范同一性和语言同一性的 ECMAScript 语言值是并非由 Symbol.for 产生的 Symbols对象。由 Symbol.for 产生的 Symbol 值具有规范同一性,但没有语言同一性。

6 ECMAScript 数据类型和值

本规范中的算法操作的值都具有关联的类型。可能的值类型正是本条款中定义的那些类型。类型进一步分为 ECMAScript 语言类型和规范类型。

6.1 ECMAScript 语言类型

ECMAScript 语言类型对应于 ECMAScript 程序员使用 ECMAScript 语言直接操作的值。ECMAScript 语言类型包括 Undefined、Null、Boolean、String、Symbol、Number、BigInt 和 Object。 ECMAScript 语言值 是由 ECMAScript 语言类型表征的值。

6.1.1 Undefined 类型

Undefined 类型只有一个值,称为 undefined。任何未赋值的变量都具有值 undefined

6.1.2 Null 类型

Null 类型只有一个值,称为 null

6.1.3 Boolean 类型

Boolean 类型表示一个逻辑实体,具有两个值,称为 truefalse

6.1.4 字符串类型

字符串类型是所有长度不超过 253 - 1 个元素的零个或多个 16 位无符号整数值(“元素”)的有序序列的集合。字符串类型通常用于在运行的 ECMAScript 程序中表示文本数据,在这种情况下,字符串中的每个元素都被视为一个 UTF-16 代码单元值。每个元素都被认为在序列中占据一个位置。这些位置用非负整数进行索引。第一个元素(如果存在)位于索引 0,下一个元素(如果存在)位于索引 1,依此类推。字符串的长度是其中元素的数量(即 16 位值的数量)。空字符串的长度为零,因此不包含任何元素。

不解释字符串内容的 ECMAScript 操作不应用任何进一步的语义。解释字符串值的操作将每个元素视为单个 UTF-16 代码单元。但是,ECMAScript 不限制这些代码单元的值或它们之间的关系,因此将字符串内容进一步解释为以 UTF-16 编码的 Unicode 码点序列的操作必须考虑到格式错误的子序列。此类操作对数值在 闭区间 0xD800 到 0xDBFF(由 Unicode 标准定义为前导代理项,或更正式地称为高位代理代码单元)内的每个代码单元以及数值在 闭区间 0xDC00 到 0xDFFF(定义为后尾代理项,或更正式地称为低位代理代码单元)内的每个代码单元应用以下规则进行特殊处理:

函数 String.prototype.normalize(参见 22.1.3.15)可用于显式规范化字符串值。String.prototype.localeCompare(参见 22.1.3.12)在内部规范化字符串值,但没有其他操作会隐式规范化它们操作的字符串。除非另有说明,否则操作结果对语言和/或区域设置不敏感。

注意

这种设计背后的基本原理是使字符串的实现尽可能简单和高性能。如果 ECMAScript 源文本采用规范化形式 C,则只要字符串字面量不包含任何 Unicode 转义序列,就可以保证它们也是规范化的。

在本规范中,短语“AB、... 的字符串连接”(其中每个参数都是字符串值、代码单元或代码单元序列)表示其代码单元序列是每个参数(按顺序)的代码单元(按顺序)连接而成的字符串值。

短语“SinclusiveStartexclusiveEnd子字符串”(其中 S 是字符串值或代码单元序列,inclusiveStartexclusiveEnd整数)表示由 S 的从索引 inclusiveStart 开始到索引 exclusiveEnd 之前结束的连续代码单元组成的字符串值(当 inclusiveStart = exclusiveEnd 时为空字符串)。如果省略“to”后缀,则使用 S 的长度作为 exclusiveEnd 的值。

短语“ASCII 词字符”表示以下字符串值,该值仅由 Unicode 基本拉丁块中的所有字母和数字以及 U+005F (LOW LINE) 组成:
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_"
由于历史原因,它对各种算法具有重要意义。

6.1.4.1 StringIndexOf ( string, searchValue, fromIndex )

抽象操作 StringIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和 fromIndex (一个非负整数),并返回一个非负整数not-found。调用时它执行以下步骤:

  1. lenstring 的长度。
  2. 如果 searchValue 是空字符串且 fromIndexlen,则返回 fromIndex
  3. searchLensearchValue 的长度。
  4. 对于每个整数 i,使得 fromIndexilen - searchLen,按升序执行:
    1. candidatestringii + searchLen子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
注1

如果 searchValue 是空字符串且 fromIndexstring 的长度,则此算法返回 fromIndex。空字符串实际上在字符串中的每个位置都能找到,包括最后一个代码单元之后。

注2

如果 fromIndex + searchValue 的长度 > string 的长度,则此算法始终返回 not-found

6.1.4.2 StringLastIndexOf ( string, searchValue, fromIndex )

抽象操作 StringLastIndexOf 接受参数 string (一个字符串)、searchValue (一个字符串) 和 fromIndex (一个非负整数),并返回一个非负整数not-found。调用时它执行以下步骤:

  1. lenstring 的长度。
  2. searchLensearchValue 的长度。
  3. 断言fromIndex + searchLenlen
  4. 对于每个整数 i,使得 0 ≤ ifromIndex,按降序执行:
    1. candidatestringii + searchLen子字符串
    2. 如果 candidatesearchValue,则返回 i
  5. 返回 not-found
注意

如果 searchValue 是空字符串,则此算法返回 fromIndex。空字符串实际上在字符串中的每个位置都能找到,包括最后一个代码单元之后。

6.1.5 Symbol 类型

Symbol 类型是所有可用作对象属性键(6.1.7)的非字符串值的集合。

每个可能的 Symbol 值都是唯一且不可变的。

每个 Symbol 值都不可变地持有一个关联值,称为 [[Description]],该值要么是 undefined,要么是字符串值。

6.1.5.1 知名符号

知名符号是本规范算法明确引用的内置 Symbol 值。它们通常用作属性的键,这些属性的值充当规范算法的扩展点。除非另有规定,否则知名符号值由所有领域9.3)共享。

在本规范中,使用标准的内在符号表示法引用知名符号,其中内在符号是表 1中列出的值之一。

注意
本规范的先前版本使用 @@name 形式的表示法,而当前版本将使用 %Symbol.name%。特别是,使用了以下名称:@@asyncIterator、@@hasInstance、@@isConcatSpreadable、@@iterator、@@match、@@matchAll、@@replace、@@search、@@species、@@split、@@toPrimitive、@@toStringTag 和 @@unscopables。
表 1:知名符号
规范名称 [[Description]] 值和用途
%Symbol.asyncIterator% "Symbol.asyncIterator" 一个返回对象默认异步迭代器的方法。由 for-await-of 语句的语义调用。
%Symbol.hasInstance% "Symbol.hasInstance" 一个确定构造函数对象是否将一个对象识别为该构造函数的实例的方法。由 instanceof 运算符的语义调用。
%Symbol.isConcatSpreadable% "Symbol.isConcatSpreadable" 一个布尔值属性,如果为 true,则表示一个对象应由 Array.prototype.concat 展平为其数组元素。
%Symbol.iterator% "Symbol.iterator" 一个返回对象默认迭代器的方法。由 for-of 语句的语义调用。
%Symbol.match% "Symbol.match" 一个正则表达式方法,用于将正则表达式与字符串进行匹配。由 String.prototype.match 方法调用。
%Symbol.matchAll% "Symbol.matchAll" 一个正则表达式方法,返回一个迭代器,该迭代器产生正则表达式与字符串匹配的结果。由 String.prototype.matchAll 方法调用。
%Symbol.replace% "Symbol.replace" 一个正则表达式方法,用于替换字符串中匹配的子字符串。由 String.prototype.replace 方法调用。
%Symbol.search% "Symbol.search" 一个正则表达式方法,返回字符串中与正则表达式匹配的索引。由 String.prototype.search 方法调用。
%Symbol.species% "Symbol.species" 一个函数值属性,是用于创建派生对象的构造函数
%Symbol.split% "Symbol.split" 一个正则表达式方法,用于在与正则表达式匹配的索引处拆分字符串。由 String.prototype.split 方法调用。
%Symbol.toPrimitive% "Symbol.toPrimitive" 一个将对象转换为相应原始值的方法。由 ToPrimitive 抽象操作调用。
%Symbol.toStringTag% "Symbol.toStringTag" 一个字符串值属性,用于创建对象的默认字符串描述。由内置方法 Object.prototype.toString 访问。
%Symbol.unscopables% "Symbol.unscopables" 一个对象值属性,其自身和继承的属性名称是从关联对象的 with 环境绑定中排除的属性名称。

6.1.6 数字类型

ECMAScript 有两种内置的数字类型:Number 和 BigInt。以下抽象操作是在这些数字类型上定义的。“结果”列显示返回类型,并指示该操作的某些调用是否可能返回突然完成

表 2:数字类型操作
操作 示例源 由 ... 的 求值 语义调用 结果
Number::unaryMinus -x 一元 - 运算符 Number
BigInt::unaryMinus BigInt
Number::bitwiseNOT ~x 按位非运算符 (~) Number
BigInt::bitwiseNOT BigInt
Number::exponentiate x ** y 求幂运算符Math.pow ( base, exponent ) Number
BigInt::exponentiate 一个包含 BigInt 的正常完成或一个抛出完成
Number::multiply x * y 乘法运算符 Number
BigInt::multiply BigInt
Number::divide x / y 乘法运算符 Number
BigInt::divide 一个包含 BigInt 的正常完成或一个抛出完成
Number::remainder x % y 乘法运算符 Number
BigInt::remainder 一个包含 BigInt 的正常完成或一个抛出完成
Number::add x ++
++ x
x + y
后缀递增运算符前缀递增运算符加法运算符 (+) Number
BigInt::add BigInt
Number::subtract x --
-- x
x - y
后缀递减运算符前缀递减运算符减法运算符 (-) Number
BigInt::subtract BigInt
Number::leftShift x << y 左移运算符 (<<) Number
BigInt::leftShift BigInt
Number::signedRightShift x >> y 有符号右移运算符 (>>) Number
BigInt::signedRightShift BigInt
Number::unsignedRightShift x >>> y 无符号右移运算符 (>>>) Number
BigInt::unsignedRightShift 一个抛出完成
Number::lessThan x < y
x > y
x <= y
x >= y
关系运算符, 通过 IsLessThan ( x, y, LeftFirst ) Boolean 或 undefined (对于无序输入)
BigInt::lessThan Boolean
Number::equal x == y
x != y
x === y
x !== y
相等运算符, 通过 IsStrictlyEqual ( x, y ) Boolean
BigInt::equal
Number::sameValue Object.is(x, y) 对象内部方法, 通过 SameValue ( x, y ), 用于测试精确值相等性 Boolean
Number::sameValueZero [x].includes(y) 通过 SameValueZero ( x, y ), 用于测试值相等性,忽略 +0𝔽-0𝔽 之间的差异, 如在 Array、Map 和 Set 方法中 Boolean
Number::bitwiseAND x & y 二元位运算符 Number
BigInt::bitwiseAND BigInt
Number::bitwiseXOR x ^ y Number
BigInt::bitwiseXOR BigInt
Number::bitwiseOR x | y Number
BigInt::bitwiseOR BigInt
Number::toString String(x) 许多表达式和内置函数,通过 ToString ( argument ) String
BigInt::toString

由于数字类型通常无法在不损失精度或截断的情况下进行转换,因此 ECMAScript 语言不提供这些类型之间的隐式转换。在调用需要另一种类型的函数时,程序员必须显式调用 NumberBigInt 函数在类型之间进行转换。

注意

ECMAScript 的第一版及后续版本为某些运算符提供了可能损失精度或截断的隐式数字转换。为了向后兼容,这些遗留的隐式转换得以保留,但为了最大限度地减少程序员出错的机会,并为未来版本中广义值类型的选择留有余地,BigInt 不提供这些转换。

6.1.6.1 Number 类型

Number 类型恰好有 18,437,736,874,454,810,627 (即 264 - 253 + 3) 个值,表示 IEEE 754-2019 二进制64位双精度浮点值,如 IEEE 二进制浮点算术标准中所指定,但 IEEE 标准中的 9,007,199,254,740,990 (即 253 - 2) 个不同的 NaN 值在 ECMAScript 中表示为单个特殊的 NaN 值。(注意,NaN 值由程序表达式 NaN 产生。)在某些实现中,外部代码可能能够检测到各种 NaN 值之间的差异,但这种行为是实现定义的;对于 ECMAScript 代码,所有 NaN 值彼此之间无法区分。

注意

在将 Number 值存储到 ArrayBuffer (参见 25.1) 或 SharedArrayBuffer (参见 25.2) 后可能观察到的位模式不一定与 ECMAScript 实现使用的该 Number 值的内部表示相同。

还有另外两个特殊值,称为正无穷大负无穷大。为简洁起见,出于说明目的,这些值也分别用符号 +∞𝔽-∞𝔽 表示。(注意,这两个无限 Number 值由程序表达式 +Infinity (或简称 Infinity) 和 -Infinity 产生。)

其余 18,437,736,874,454,810,624 (即 264 - 253) 个值称为有限数。其中一半是正数,一半是负数;对于每个有限正 Number 值,都有一个对应的具有相同大小的负值。

注意,既有正零也有负零。为简洁起见,出于说明目的,这些值也分别用符号 +0𝔽-0𝔽 表示。(注意,这两个不同的零 Number 值由程序表达式 +0 (或简称 0) 和 -0 产生。)

18,437,736,874,454,810,622 (即 264 - 253 - 2) 个有限非零值有两种:

其中 18,428,729,675,200,069,632 (即 264 - 254) 个是规范化的,形式为

s × m × 2e

其中 s 是 1 或 -1,m区间 [252, 253) 内的整数e闭区间 [-1074, 971] 内的整数

其余 9,007,199,254,740,990 (即 253 - 2) 个值是非规范化的,形式为

s × m × 2e

其中 s 是 1 或 -1,m区间 (0, 252) 内的整数e 是 -1074。

注意,所有大小不超过 253 的正负整数都可以在 Number 类型中表示。整数 0 在 Number 类型中有两种表示:+0𝔽-0𝔽

如果一个有限数非零,并且用于表示它(以上述两种形式之一)的整数 m 是奇数,则该数具有奇数有效数。否则,它具有偶数有效数

在本规范中,短语“xNumber 值”(其中 x 表示一个精确的实数数学量,甚至可能是一个无理数,如 π)指的是按以下方式选择的 Number 值。考虑 Number 类型的所有有限值的集合,去掉 -0𝔽,并向其添加两个 Number 类型中无法表示的附加值,即 21024 (即 +1 × 253 × 2971) 和 -21024 (即 -1 × 253 × 2971)。选择此集合中与 x 值最接近的成员。如果集合中的两个值同样接近,则选择具有偶数有效数的那个;为此,两个额外的值 21024-21024 被认为具有偶数有效数。最后,如果选择了 21024,则将其替换为 +∞𝔽;如果选择了 -21024,则将其替换为 -∞𝔽;如果选择了 +0𝔽,则当且仅当 x < 0 时将其替换为 -0𝔽;任何其他选择的值保持不变。结果是 xNumber 值。(此过程与 IEEE 754-2019 roundTiesToEven 模式的行为完全对应。)

+∞ 的Number 值+∞𝔽,-∞ 的Number 值-∞𝔽

某些 ECMAScript 运算符仅处理特定范围内的整数,例如闭区间 [-231, 231 - 1] 或闭区间 [0, 216 - 1]。这些运算符接受 Number 类型的任何值,但首先将每个此类值转换为预期范围内的整数值。请参见 7.1 中数字转换操作的说明。

6.1.6.1.1 Number::unaryMinus ( x )

抽象操作 Number::unaryMinus 接受参数 x (一个 Number) 并返回一个 Number。调用时它执行以下步骤:

  1. 如果 xNaN,则返回 NaN
  2. 返回 x 的负值;即,计算一个具有相同大小但符号相反的 Number。

6.1.6.1.2 Number::bitwiseNOT ( x )

抽象操作 Number::bitwiseNOT 接受参数 x (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. oldValue 为 ! ToInt32(x)。
  2. 返回 oldValue 的按位补码。结果的数学值可以精确地表示为一个 32 位二进制补码位串。

6.1.6.1.3 Number::exponentiate ( base, exponent )

抽象操作 Number::exponentiate 接受参数 base (一个 Number) 和 exponent (一个 Number) 并返回一个 Number。它返回一个实现近似的值,表示 baseexponent 次幂的结果。调用时它执行以下步骤:

  1. 如果 exponentNaN,则返回 NaN
  2. 如果 exponent+0𝔽-0𝔽,则返回 1𝔽
  3. 如果 baseNaN,则返回 NaN
  4. 如果 base+∞𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +∞𝔽。否则,返回 +0𝔽
  5. 如果 base-∞𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是一个奇数整数 Number,则返回 -∞𝔽。否则,返回 +∞𝔽
    2. 否则,
      1. 如果 exponent 是一个奇数整数 Number,则返回 -0𝔽。否则,返回 +0𝔽
  6. 如果 base+0𝔽,则
    1. 如果 exponent > +0𝔽,则返回 +0𝔽。否则,返回 +∞𝔽
  7. 如果 base-0𝔽,则
    1. 如果 exponent > +0𝔽,则
      1. 如果 exponent 是一个奇数整数 Number,则返回 -0𝔽。否则,返回 +0𝔽
    2. 否则,
      1. 如果 exponent 是一个奇数整数 Number,则返回 -∞𝔽。否则,返回 +∞𝔽
  8. 断言base有限的,并且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 exponent+∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +∞𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +0𝔽
  10. 如果 exponent-∞𝔽,则
    1. 如果 abs((base)) > 1,则返回 +0𝔽
    2. 如果 abs((base)) = 1,则返回 NaN
    3. 如果 abs((base)) < 1,则返回 +∞𝔽
  11. 断言exponent有限的,并且既不是 +0𝔽 也不是 -0𝔽
  12. 如果 base < -0𝔽exponent 不是一个整数 Number,则返回 NaN
  13. 返回一个实现近似的 Number 值,表示 (base) 的 (exponent) 次幂的结果。
注意

base1𝔽-1𝔽exponent+∞𝔽-∞𝔽 时,或者当 base1𝔽exponentNaN 时,base ** exponent 的结果与 IEEE 754-2019 不同。ECMAScript 的第一版为此操作指定了 NaN 的结果,而 IEEE 754 的后续修订版指定了 1𝔽。出于兼容性原因,保留了历史上的 ECMAScript 行为。

6.1.6.1.4 Number::multiply ( x, y )

抽象操作 Number::multiply 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行乘法,产生 xy 的乘积。调用时它执行以下步骤:

  1. 如果 xNaNyNaN,则返回 NaN
  2. 如果 x+∞𝔽-∞𝔽,则
    1. 如果 y+0𝔽-0𝔽,则返回 NaN
    2. 如果 y > +0𝔽,则返回 x
    3. 返回 -x
  3. 如果 y+∞𝔽-∞𝔽,则
    1. 如果 x+0𝔽-0𝔽,则返回 NaN
    2. 如果 x > +0𝔽,则返回 y
    3. 返回 -y
  4. 如果 x-0𝔽,则
    1. 如果 y-0𝔽y < -0𝔽,则返回 +0𝔽
    2. 否则,返回 -0𝔽
  5. 如果 y-0𝔽,则
    1. 如果 x < -0𝔽,则返回 +0𝔽
    2. 否则,返回 -0𝔽
  6. 返回 𝔽((x) × (y))。
注意

有限精度乘法是可交换的,但并非总是结合的。

6.1.6.1.5 Number::divide ( x, y )

抽象操作 Number::divide 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行除法,产生 xy 的商,其中 x 是被除数,y 是除数。调用时它执行以下步骤:

  1. 如果 xNaNyNaN,则返回 NaN
  2. 如果 x+∞𝔽-∞𝔽,则
    1. 如果 y+∞𝔽-∞𝔽,则返回 NaN
    2. 如果 y+0𝔽y > +0𝔽,则返回 x
    3. 返回 -x
  3. 如果 y+∞𝔽,则
    1. 如果 x+0𝔽x > +0𝔽,则返回 +0𝔽。否则,返回 -0𝔽
  4. 如果 y-∞𝔽,则
    1. 如果 x+0𝔽x > +0𝔽,则返回 -0𝔽。否则,返回 +0𝔽
  5. 如果 x+0𝔽-0𝔽,则
    1. 如果 y+0𝔽-0𝔽,则返回 NaN
    2. 如果 y > +0𝔽,则返回 x
    3. 返回 -x
  6. 如果 y+0𝔽,则
    1. 如果 x > +0𝔽,则返回 +∞𝔽。否则,返回 -∞𝔽
  7. 如果 y-0𝔽,则
    1. 如果 x > +0𝔽,则返回 -∞𝔽。否则,返回 +∞𝔽
  8. 返回 𝔽((x) / (y))。

6.1.6.1.6 Number::remainder ( n, d )

抽象操作 Number::remainder 接受参数 n (一个 Number) 和 d (一个 Number) 并返回一个 Number。它产生其操作数隐式除法的余数,其中 n 是被除数,d 是除数。调用时它执行以下步骤:

  1. 如果 nNaNdNaN,则返回 NaN
  2. 如果 n+∞𝔽-∞𝔽,则返回 NaN
  3. 如果 d+∞𝔽-∞𝔽,则返回 n
  4. 如果 d+0𝔽-0𝔽,则返回 NaN
  5. 如果 n+0𝔽-0𝔽,则返回 n
  6. 断言nd有限的且非零。
  7. quotient(n) / (d)。
  8. qtruncate(quotient)。
  9. r(n) - ((d) × q)。
  10. 如果 r = 0 且 n < -0𝔽,则返回 -0𝔽
  11. 返回 𝔽(r)。
注1

在 C 和 C++ 中,余数运算符仅接受整数操作数;在 ECMAScript 中,它也接受浮点操作数。

注2
% 运算符计算的浮点余数运算的结果与 IEEE 754-2019 定义的“余数”运算不同。IEEE 754-2019 “余数”运算计算的是舍入除法的余数,而不是截断除法的余数,因此其行为与通常的整数余数运算符不同。相反,ECMAScript 语言定义 % 在浮点运算上的行为类似于 Java 整数余数运算符的行为;这可以与 C 库函数 fmod 进行比较。

6.1.6.1.7 Number::add ( x, y )

抽象操作 Number::add 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它根据 IEEE 754-2019 二进制双精度算术规则执行加法,产生其参数的和。调用时它执行以下步骤:

  1. 如果 xNaNyNaN,则返回 NaN
  2. 如果 x+∞𝔽y-∞𝔽,则返回 NaN
  3. 如果 x-∞𝔽y+∞𝔽,则返回 NaN
  4. 如果 x+∞𝔽-∞𝔽,则返回 x
  5. 如果 y+∞𝔽-∞𝔽,则返回 y
  6. 断言xy 都是有限的
  7. 如果 x-0𝔽y-0𝔽,则返回 -0𝔽
  8. 返回 𝔽((x) + (y))。
注意

有限精度加法是可交换的,但并非总是结合的。

6.1.6.1.8 Number::subtract ( x, y )

抽象操作 Number::subtract 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Number。它执行减法,产生其操作数的差;x 是被减数,y 是减数。调用时它执行以下步骤:

  1. 返回 Number::add(x, Number::unaryMinus(y))。
注意

x - y 总是产生与 x + (-y) 相同的结果。

6.1.6.1.9 Number::leftShift ( x, y )

抽象操作 Number::leftShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) modulo 32。
  4. 返回将 lNum 左移 shiftCount 位的结果。结果的数学值可以精确地表示为一个 32 位二进制补码位串。

6.1.6.1.10 Number::signedRightShift ( x, y )

抽象操作 Number::signedRightShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) modulo 32。
  4. 返回对 lNum 执行符号扩展右移 shiftCount 位的结果。最高有效位被传播。结果的数学值可以精确地表示为一个 32 位二进制补码位串。

6.1.6.1.11 Number::unsignedRightShift ( x, y )

抽象操作 Number::unsignedRightShift 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. lNum 为 ! ToUint32(x)。
  2. rNum 为 ! ToUint32(y)。
  3. shiftCount(rNum) modulo 32。
  4. 返回对 lNum 执行零填充右移 shiftCount 位的结果。空出的位用零填充。结果的数学值可以精确地表示为一个 32 位无符号位串。

6.1.6.1.12 Number::lessThan ( x, y )

抽象操作 Number::lessThan 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean 或 undefined。调用时它执行以下步骤:

  1. 如果 xNaN,则返回 undefined
  2. 如果 yNaN,则返回 undefined
  3. 如果 xy,则返回 false
  4. 如果 x+0𝔽y-0𝔽,则返回 false
  5. 如果 x-0𝔽y+0𝔽,则返回 false
  6. 如果 x+∞𝔽,则返回 false
  7. 如果 y+∞𝔽,则返回 true
  8. 如果 y-∞𝔽,则返回 false
  9. 如果 x-∞𝔽,则返回 true
  10. 断言xy有限的
  11. 如果 (x) < (y),则返回 true。否则,返回 false

6.1.6.1.13 Number::equal ( x, y )

抽象操作 Number::equal 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  1. 如果 xNaN,则返回 false
  2. 如果 yNaN,则返回 false
  3. 如果 xy,则返回 true
  4. 如果 x+0𝔽y-0𝔽,则返回 true
  5. 如果 x-0𝔽y+0𝔽,则返回 true
  6. 返回 false

6.1.6.1.14 Number::sameValue ( x, y )

抽象操作 Number::sameValue 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 false
  3. 如果 x-0𝔽y+0𝔽,则返回 false
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.15 Number::sameValueZero ( x, y )

抽象操作 Number::sameValueZero 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个 Boolean。调用时它执行以下步骤:

  1. 如果 xNaNyNaN,则返回 true
  2. 如果 x+0𝔽y-0𝔽,则返回 true
  3. 如果 x-0𝔽y+0𝔽,则返回 true
  4. 如果 xy,则返回 true
  5. 返回 false

6.1.6.1.16 NumberBitwiseOp ( op, x, y )

抽象操作 NumberBitwiseOp 接受参数 op (&^|)、x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. lNum 为 ! ToInt32(x)。
  2. rNum 为 ! ToInt32(y)。
  3. lBits 为表示 (lNum) 的 32 位二进制补码位串。
  4. rBits 为表示 (rNum) 的 32 位二进制补码位串。
  5. 如果 op&,则
    1. result 为对 lBitsrBits 应用按位与运算的结果。
  6. 否则,如果 op^,则
    1. result 为对 lBitsrBits 应用按位异或 (XOR) 运算的结果。
  7. 否则,
    1. 断言op|
    2. result 为对 lBitsrBits 应用按位或运算的结果。
  8. 返回由 32 位二进制补码位串 result 表示的整数Number 值

6.1.6.1.17 Number::bitwiseAND ( x, y )

抽象操作 Number::bitwiseAND 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. 返回 NumberBitwiseOp(&, x, y)。

6.1.6.1.18 Number::bitwiseXOR ( x, y )

抽象操作 Number::bitwiseXOR 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. 返回 NumberBitwiseOp(^, x, y)。

6.1.6.1.19 Number::bitwiseOR ( x, y )

抽象操作 Number::bitwiseOR 接受参数 x (一个 Number) 和 y (一个 Number) 并返回一个整数 Number。调用时它执行以下步骤:

  1. 返回 NumberBitwiseOp(|, x, y)。

6.1.6.1.20 Number::toString ( x, radix )

抽象操作 Number::toString 接受参数 x (一个 Number) 和 radix (一个闭区间 [2, 36] 内的整数) 并返回一个 String。它使用基数为 radix 的位置数字系统将 x 表示为字符串。使用基数 r 表示数字时使用的数字取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个代码单元(按顺序)。大小大于或等于 1𝔽 的数字的表示永远不包含前导零。调用时它执行以下步骤:

  1. 如果 xNaN,则返回 "NaN"
  2. 如果 x+0𝔽-0𝔽,则返回 "0"
  3. 如果 x < -0𝔽,则返回字符串连接 "-"Number::toString(-x, radix)。
  4. 如果 x+∞𝔽,则返回 "Infinity"
  5. nks整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。注意,k 是使用基数 radix 表示 s 的位数,s 不能被 radix 整除,并且 s 的最低有效位不一定由这些标准唯一确定。
  6. 如果 radix ≠ 10 或 n闭区间 [-5, 21] 内,则
    1. 如果 nk,则
      1. 返回以下各项的字符串连接
        • 使用基数 radix 表示 sk 位数字的代码单元
        • n - k 个代码单元 0x0030 (DIGIT ZERO)
    2. 否则,如果 n > 0,则
      1. 返回以下各项的字符串连接
        • 使用基数 radix 表示 s 的最高有效 n 位数字的代码单元
        • 代码单元 0x002E (FULL STOP)
        • 使用基数 radix 表示 s 的其余 k - n 位数字的代码单元
    3. 否则,
      1. 断言n ≤ 0。
      2. 返回以下各项的字符串连接
        • 代码单元 0x0030 (DIGIT ZERO)
        • 代码单元 0x002E (FULL STOP)
        • -n 个代码单元 0x0030 (DIGIT ZERO)
        • 使用基数 radix 表示 sk 位数字的代码单元
  7. 注意:在这种情况下,输入将使用科学 E 表示法表示,例如 1.2e+3
  8. 断言radix 是 10。
  9. 如果 n < 0,则
    1. exponentSign 为代码单元 0x002D (HYPHEN-MINUS)。
  10. 否则,
    1. exponentSign 为代码单元 0x002B (PLUS SIGN)。
  11. 如果 k = 1,则
    1. 返回以下各项的字符串连接
      • s 的单个数字的代码单元
      • 代码单元 0x0065 (LATIN SMALL LETTER E)
      • exponentSign
      • abs(n - 1) 的十进制表示的代码单元
  12. 返回以下各项的字符串连接
    • s 的十进制表示的最高有效数字的代码单元
    • 代码单元 0x002E (FULL STOP)
    • s 的十进制表示的其余 k - 1 位数字的代码单元
    • 代码单元 0x0065 (LATIN SMALL LETTER E)
    • exponentSign
    • abs(n - 1) 的十进制表示的代码单元
注1

以下观察结果可能对实现有所帮助,但并非本标准的规范性要求的一部分:

  • 如果 x 是除 -0𝔽 之外的任何 Number 值,则 ToNumber(ToString(x)) 是 x。
  • s 的最低有效位不一定由步骤 5 中列出的要求唯一确定。
注2

对于提供比上述规则要求的转换更精确的实现,建议使用以下步骤 5 的替代版本作为指导:

  1. nks整数,使得 k ≥ 1,radixk - 1s < radixk𝔽(s × radixn - k) 是 x,并且 k 尽可能小。如果 s 有多种可能性,则选择使 s × radixn - k 的值最接近 (x) 的 s 值。如果存在两个这样的 s 可能值,则选择偶数那个。注意,k 是使用基数 radix 表示 s 的位数,并且 s 不能被 radix 整除。
注3

ECMAScript 的实现者可能会发现 David M. Gay 编写的用于浮点数二进制到十进制转换的论文和代码很有用:

Gay, David M. Correctly Rounded Binary-Decimal and Decimal-Binary Conversions. Numerical Analysis, Manuscript 90-10. AT&T Bell Laboratories (Murray Hill, New Jersey). 1990年11月30日。可从以下网址获取:
https://ampl.com/_archive/first-website/REFS/rounding.pdf。 相关代码可从以下网址获取:
http://netlib.sandia.gov/fp/dtoa.c
http://netlib.sandia.gov/fp/g_fmt.c 也可以在各种 netlib 镜像站点找到。

6.1.6.2 BigInt 类型

BigInt 类型表示一个整数值。该值可以是任意大小,不限于特定的位宽。一般来说,除非另有说明,操作被设计为返回精确的基于数学的答案。对于二进制操作,BigInt 表现为二进制补码字符串,负数被视为左侧无限设置位。

6.1.6.2.1 BigInt::unaryMinus ( x )

抽象操作 BigInt::unaryMinus 接受参数 x(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 如果 x = 0,返回 0
  2. 返回 -x

6.1.6.2.2 BigInt::bitwiseNOT ( x )

抽象操作 BigInt::bitwiseNOT 接受参数 x(一个 BigInt)并返回一个 BigInt。它返回 x 的一的补码。调用时执行以下步骤:

  1. 返回 -x - 1

6.1.6.2.3 BigInt::exponentiate ( base, exponent )

抽象操作 BigInt::exponentiate 接受参数 base(一个 BigInt)和 exponent(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 exponent < 0,抛出 RangeError 异常。
  2. 如果 base = 0exponent = 0,返回 1
  3. 返回 baseexponent 次幂。

6.1.6.2.4 BigInt::multiply ( x, y )

抽象操作 BigInt::multiply 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 x × y
注意
即使结果的位宽比输入大得多,也会给出精确的数学答案。

6.1.6.2.5 BigInt::divide ( x, y )

抽象操作 BigInt::divide 接受参数 x(一个 BigInt)和 y(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 y = 0,抛出 RangeError 异常。
  2. quotient(x) / (y)。
  3. 返回 (truncate(quotient))。

6.1.6.2.6 BigInt::remainder ( n, d )

抽象操作 BigInt::remainder 接受参数 n(一个 BigInt)和 d(一个 BigInt),返回包含 BigInt 的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 d = 0,抛出 RangeError 异常。
  2. 如果 n = 0,返回 0
  3. quotient(n) / (d)。
  4. q(truncate(quotient))。
  5. 返回 n - (d × q)。
注意
结果的符号是被除数的符号。

6.1.6.2.7 BigInt::add ( x, y )

抽象操作 BigInt::add 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 x + y

6.1.6.2.8 BigInt::subtract ( x, y )

抽象操作 BigInt::subtract 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 x - y

6.1.6.2.9 BigInt::leftShift ( x, y )

抽象操作 BigInt::leftShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 如果 y < 0,则
    1. 返回 (floor((x) / 2-(y)))。
  2. 返回 x × 2y
注意
这里的语义应该等同于按位移位,将 BigInt 视为无限长度的二进制补码数字字符串。

6.1.6.2.10 BigInt::signedRightShift ( x, y )

抽象操作 BigInt::signedRightShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 BigInt::leftShift(x, -y)。

6.1.6.2.11 BigInt::unsignedRightShift ( x, y )

抽象操作 BigInt::unsignedRightShift 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回抛出完成。调用时执行以下步骤:

  1. 抛出 TypeError 异常。

6.1.6.2.12 BigInt::lessThan ( x, y )

抽象操作 BigInt::lessThan 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个布尔值。调用时执行以下步骤:

  1. 如果 (x) < (y),返回 true;否则返回 false

6.1.6.2.13 BigInt::equal ( x, y )

抽象操作 BigInt::equal 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个布尔值。调用时执行以下步骤:

  1. 如果 (x) = (y),返回 true;否则返回 false

6.1.6.2.14 BinaryAnd ( x, y )

抽象操作 BinaryAnd 接受参数 x(0 或 1)和 y(0 或 1)并返回 0 或 1。调用时执行以下步骤:

  1. 如果 x = 1 且 y = 1,返回 1。
  2. 否则,返回 0。

6.1.6.2.15 BinaryOr ( x, y )

抽象操作 BinaryOr 接受参数 x(0 或 1)和 y(0 或 1)并返回 0 或 1。调用时执行以下步骤:

  1. 如果 x = 1 或 y = 1,返回 1。
  2. 否则,返回 0。

6.1.6.2.16 BinaryXor ( x, y )

抽象操作 BinaryXor 接受参数 x(0 或 1)和 y(0 或 1)并返回 0 或 1。调用时执行以下步骤:

  1. 如果 x = 1 且 y = 0,返回 1。
  2. 否则如果 x = 0 且 y = 1,返回 1。
  3. 否则,返回 0。

6.1.6.2.17 BigIntBitwiseOp ( op, x, y )

抽象操作 BigIntBitwiseOp 接受参数 op&^|)、x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 设置 x(x)。
  2. 设置 y(y)。
  3. result 为 0。
  4. shift 为 0。
  5. 重复执行,直到 (x = 0 或 x = -1) 且 (y = 0 或 y = -1):
    1. xDigitx modulo 2。
    2. yDigity modulo 2。
    3. 如果 op&,则
      1. 设置 resultresult + 2shift × BinaryAnd(xDigit, yDigit)。
    4. 否则如果 op|,则
      1. 设置 resultresult + 2shift × BinaryOr(xDigit, yDigit)。
    5. 否则,
      1. 断言op^
      2. 设置 resultresult + 2shift × BinaryXor(xDigit, yDigit)。
    6. 设置 shiftshift + 1。
    7. 设置 x 为 (x - xDigit) / 2。
    8. 设置 y 为 (y - yDigit) / 2。
  6. 如果 op&,则
    1. tmpBinaryAnd(x modulo 2, y modulo 2)。
  7. 否则如果 op|,则
    1. tmpBinaryOr(x modulo 2, y modulo 2)。
  8. 否则,
    1. 断言op^
    2. tmpBinaryXor(x modulo 2, y modulo 2)。
  9. 如果 tmp ≠ 0,则
    1. 设置 resultresult - 2shift
    2. 注意:这扩展了符号。
  10. 返回 resultBigInt 值

6.1.6.2.18 BigInt::bitwiseAND ( x, y )

抽象操作 BigInt::bitwiseAND 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(&, x, y)。

6.1.6.2.19 BigInt::bitwiseXOR ( x, y )

抽象操作 BigInt::bitwiseXOR 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(^, x, y)。

6.1.6.2.20 BigInt::bitwiseOR ( x, y )

抽象操作 BigInt::bitwiseOR 接受参数 x(一个 BigInt)和 y(一个 BigInt)并返回一个 BigInt。调用时执行以下步骤:

  1. 返回 BigIntBitwiseOp(|, x, y)。

6.1.6.2.21 BigInt::toString ( x, radix )

抽象操作 BigInt::toString 接受参数 x(一个 BigInt)和 radix(一个在 2 到 36 的闭区间内的整数)并返回一个字符串。它使用基数为 radix 的位置记数法将 x 表示为字符串。在基数为 r 的 BigInt 表示中使用的数字取自 "0123456789abcdefghijklmnopqrstuvwxyz" 的前 r 个代码单元。除了 0 之外的 BigInt 表示从不包含前导零。调用时执行以下步骤:

  1. 如果 x < 0,返回 "-"BigInt::toString(-x, radix) 的字符串连接
  2. 返回使用基数 radix 表示 x 的字符串值。

6.1.7 Object 类型

Object 类型的每个实例,也简称为"一个 Object",表示属性的集合。每个属性要么是数据属性,要么是访问器属性:

  • 数据属性将键值与ECMAScript 语言值和一组布尔属性关联。
  • 访问器属性将键值与一个或两个访问器函数以及一组布尔属性关联。访问器函数用于存储或检索与该属性关联的ECMAScript 语言值

对象的属性使用属性键唯一标识。属性键要么是字符串,要么是符号。所有字符串和符号(包括空字符串)都可以作为属性键属性名字符串类型的属性键

整数索引属性名 n,使得 CanonicalNumericIndexString(n) 返回闭区间+0𝔽𝔽(253 - 1) 的整数数组索引整数索引 n,使得 CanonicalNumericIndexString(n) 返回闭区间+0𝔽𝔽(232 - 2) 的整数

注意

每个非负安全整数都有对应的整数索引。除了 232 - 1 之外的每个 32 位无符号整数都有对应的数组索引"-0" 既不是整数索引也不是数组索引

属性键用于访问属性及其值。属性有两种访问方式:getset,分别对应值检索和赋值。通过 get 和 set 访问的属性包括作为对象直接部分的自有属性和通过属性继承关系由另一个关联对象提供的继承属性。继承属性可能是关联对象的自有属性或继承属性。对象的每个自有属性都必须具有与该对象的其他自有属性的键值不同的键值。

所有对象在逻辑上都是属性的集合,但存在多种形式的对象,它们在访问和操作属性的语义上有所不同。请参见6.1.7.2了解多种形式对象的定义。

此外,某些对象是可调用的;这些被称为函数或函数对象,下面将进一步描述。ECMAScript 中的所有函数都是 Object 类型的成员。

6.1.7.1 属性特性

本规范使用特性来定义和解释 Object 属性的状态,如表 3所述。除非明确指定,否则每个特性的初始值是其默认值。

表 3:Object 属性的特性
特性名称 存在该特性的属性类型 值域 默认值 描述
[[Value]] 数据属性 ECMAScript 语言值 undefined 通过对属性的 get 访问检索到的值。
[[Writable]] 数据属性 布尔值 false 如果为 false,ECMAScript 代码尝试使用 [[Set]] 更改属性的 [[Value]] 特性将不会成功。
[[Get]] 访问器属性 Object 或 undefined undefined 如果值是一个 Object,它必须是函数对象。每当执行对属性的 get 访问时,都会使用空参数列表调用该函数的 [[Call]] 内部方法(表 5)来检索属性值。
[[Set]] 访问器属性 Object 或 undefined undefined 如果值是一个 Object,它必须是函数对象。每当执行对属性的 set 访问时,都会使用包含赋值作为其唯一参数的参数列表调用该函数的 [[Call]] 内部方法(表 5)。属性的 [[Set]] 内部方法的效果可能但不一定会影响后续调用属性的 [[Get]] 内部方法返回的值。
[[Enumerable]] 数据属性访问器属性 布尔值 false 如果为 true,该属性将被 for-in 枚举(参见14.7.5)枚举。否则,该属性被称为不可枚举的。
[[Configurable]] 数据属性访问器属性 布尔值 false 如果为 false,尝试删除属性、将其从数据属性更改为访问器属性或从访问器属性更改为数据属性,或对其特性进行任何更改(除了替换现有的 [[Value]] 或将 [[Writable]] 设置为 false)都将失败。

6.1.7.2 对象内部方法和内部槽

在 ECMAScript 中,对象的实际语义通过称为内部方法的算法指定。ECMAScript 引擎中的每个对象都与一组定义其运行时行为的内部方法相关联。这些内部方法不是 ECMAScript 语言的一部分。它们由本规范纯粹为了解释目的而定义。但是,ECMAScript 实现中的每个对象都必须按照与其关联的内部方法所指定的方式行为。实现这一点的确切方式由实现决定。

内部方法名称是多态的。这意味着当在不同的对象值上调用相同的内部方法名称时,可能执行不同的算法。实际调用内部方法的对象是调用的"目标"。如果在运行时,算法的实现尝试使用对象不支持的内部方法,则抛出 TypeError 异常。

内部槽对应于与对象关联并由各种 ECMAScript 规范算法使用的内部状态。内部槽不是对象属性,它们不被继承。根据特定的内部槽规范,这种状态可能由任何ECMAScript 语言类型的值或特定 ECMAScript 规范类型值组成。除非明确指定,否则内部槽作为创建对象过程的一部分分配,并且不能动态添加到对象中。除非另有指定,内部槽的初始值是 undefined。本规范中的各种算法创建具有内部槽的对象。但是,ECMAScript 语言没有提供将内部槽与对象关联的直接方法。

所有对象都有一个名为 [[PrivateElements]] 的内部槽,它是PrivateElements列表。这个列表表示对象的私有字段、方法和访问器的值。最初,它是一个空列表

内部方法和内部槽在本规范中使用双方括号 [[ ]] 括起来的名称标识。

表 4总结了本规范使用的基本内部方法,适用于 ECMAScript 代码创建或操作的所有对象。每个对象都必须具有所有基本内部方法的算法。但是,并非所有对象都必须为这些方法使用相同的算法。

普通对象是满足以下所有条件的对象:

  • 对于表 4中列出的内部方法,对象使用10.1中定义的那些。
  • 如果对象有 [[Call]] 内部方法,它使用10.2.1中定义的或10.3.1中定义的。
  • 如果对象有 [[Construct]] 内部方法,它使用10.2.2中定义的或10.3.2中定义的。

异质对象是不是普通对象的对象。

本规范通过对象的内部方法识别不同种类的异质对象。行为上等同于特定种类异质对象(如数组异质对象绑定函数异质对象)但没有为该种类指定的相同内部方法集合的对象,不被识别为该种类的异质对象

表 4和其他类似表的"签名"列描述了每个内部方法的调用模式。调用模式总是包括描述性参数名称的括号列表。如果参数名称与 ECMAScript 类型名称相同,则该名称描述参数值的所需类型。如果内部方法明确返回值,其参数列表后跟符号"→"和返回值的类型名称。签名中使用的类型名称指的是第6节中定义的类型,并由以下附加名称扩展。"any"意味着该值可能是任何ECMAScript 语言类型

除了参数之外,内部方法始终可以访问作为方法调用目标的对象。

内部方法隐式返回完成记录,要么是包装其调用模式中显示的返回类型值的正常完成,要么是抛出完成

表 4:基本内部方法
内部方法 签名 描述
[[GetPrototypeOf]] ( ) Object | Null 确定为此对象提供继承属性的对象。null 值表示没有继承属性。
[[SetPrototypeOf]] (Object | Null) Boolean 将此对象与提供继承属性的另一个对象关联。传递 null 表示没有继承属性。返回 true 表示操作成功完成,或 false 表示操作不成功。
[[IsExtensible]] ( ) Boolean 确定是否允许向此对象添加额外属性。
[[PreventExtensions]] ( ) Boolean 控制是否可以向此对象添加新属性。如果操作成功则返回 true,如果操作不成功则返回 false
[[GetOwnProperty]] (propertyKey) Undefined | Property Descriptor 返回此对象键为 propertyKey 的自有属性的属性描述符,如果不存在这样的属性则返回 undefined
[[DefineOwnProperty]] (propertyKey, PropertyDescriptor) Boolean 创建或更改键为 propertyKey 的自有属性,使其具有 PropertyDescriptor 描述的状态。如果该属性成功创建/更新则返回 true,如果无法创建或更新该属性则返回 false
[[HasProperty]] (propertyKey) Boolean 返回布尔值,表示此对象是否已经具有键为 propertyKey 的自有或继承属性。
[[Get]] (propertyKey, Receiver) any 从此对象返回键为 propertyKey 的属性值。如果必须执行任何 ECMAScript 代码来检索属性值,Receiver 用作评估代码时的 this 值。
[[Set]] (propertyKey, value, Receiver) Boolean 将键为 propertyKey 的属性值设置为 value。如果必须执行任何 ECMAScript 代码来设置属性值,Receiver 用作评估代码时的 this 值。如果属性值已设置则返回 true,如果无法设置则返回 false
[[Delete]] (propertyKey) Boolean 从此对象中删除键为 propertyKey 的自有属性。如果属性未被删除且仍然存在则返回 false。如果属性已被删除或不存在则返回 true
[[OwnPropertyKeys]] ( ) List of property keys 返回一个列表,其元素是对象的所有自有属性键

表 5总结了可作为函数调用的对象支持的额外基本内部方法。函数对象是支持 [[Call]] 内部方法的对象。构造器是支持 [[Construct]] 内部方法的对象。每个支持 [[Construct]] 的对象都必须支持 [[Call]];也就是说,每个构造器都必须是函数对象。因此,构造器也可以称为构造器函数构造器函数对象

表 5:函数对象的额外基本内部方法
内部方法 签名 描述
[[Call]] (any, a List of any) any 执行与此对象关联的代码。通过函数调用表达式调用。内部方法的参数是 this 值和一个列表,其元素是通过调用表达式传递给函数的参数。实现此内部方法的对象是可调用的
[[Construct]] (a List of any, Object) Object 创建对象。通过 new 操作符或 super 调用调用。内部方法的第一个参数是一个列表,其元素是构造器调用或 super 调用的参数。第二个参数是最初应用 new 操作符的对象。实现此内部方法的对象称为构造器函数对象不一定是构造器,这种非构造器函数对象没有 [[Construct]] 内部方法。

普通对象和标准异质对象的基本内部方法的语义在第10节中指定。如果实现不支持异质对象的内部方法的任何指定使用,则在尝试时该使用必须抛出 TypeError 异常。

6.1.7.3 基本内部方法的不变式

ECMAScript 引擎中对象的内部方法必须符合下面指定的不变式列表。本规范中的普通 ECMAScript 对象以及所有标准异质对象都保持这些不变式。ECMAScript 代理对象通过对 [[ProxyHandler]] 对象上调用的陷阱结果进行运行时检查来维持这些不变式。

任何实现提供的异质对象也必须为这些对象维持这些不变式。违反这些不变式可能导致 ECMAScript 代码出现不可预测的行为并产生安全问题。但是,违反这些不变式绝不能损害实现的内存安全。

实现不得允许以任何方式规避这些不变式,例如通过提供实现基本内部方法功能但不强制执行其不变式的替代接口。

定义:

  • 内部方法的 目标 是调用内部方法的对象。
  • 如果目标被观察到从其 [[IsExtensible]] 内部方法返回 false,或从其 [[PreventExtensions]] 内部方法返回 true,则目标是 不可扩展的
  • 不存在的 属性是在不可扩展目标上不作为自有属性存在的属性。
  • 所有对 SameValue 的引用都根据 SameValue 算法的定义。

返回值:

任何内部方法返回的值必须是一个完成记录,具有以下之一:

  • [[Type]] = normal[[Target]] = empty,并且 [[Value]] = 下面为该内部方法显示的"正常返回类型"的值,或
  • [[Type]] = throw[[Target]] = empty,并且 [[Value]] = 任何ECMAScript 语言值
注意 1

内部方法不得返回continue 完成break 完成return 完成

[[GetPrototypeOf]] ( )

  • 正常返回类型是 Object 或 Null。
  • 如果目标是不可扩展的,并且 [[GetPrototypeOf]] 返回值 V,那么将来对 [[GetPrototypeOf]] 的所有调用都应该返回与 V SameValue 相同的值。
注意 2

对象的原型链应该具有有限长度(即,从任何对象开始,递归地将 [[GetPrototypeOf]] 内部方法应用于其结果最终应该导致值 null)。但是,如果原型链包含任何不使用普通对象[[GetPrototypeOf]] 定义的异质对象,则此要求无法作为对象级不变式强制执行。这样的循环原型链在访问对象属性时可能导致无限循环。

[[SetPrototypeOf]] ( V )

  • 正常返回类型是 Boolean。
  • 如果目标是不可扩展的,[[SetPrototypeOf]] 必须返回 false,除非 V 与目标观察到的 [[GetPrototypeOf]] 值为SameValue

[[IsExtensible]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[IsExtensible]] 返回 false,将来在目标上的所有 [[IsExtensible]] 调用必须返回 false

[[PreventExtensions]] ( )

  • 正常返回类型是 Boolean。
  • 如果 [[PreventExtensions]] 返回 true,将来在目标上的所有 [[IsExtensible]] 调用必须返回 false,并且目标现在被视为不可扩展的。

[[GetOwnProperty]] ( P )

  • 正常返回类型是属性描述符或 Undefined。
  • 如果返回值是属性描述符,它必须是一个完全填充的属性描述符
  • 如果 P 被描述为不可配置、不可写的自有数据属性,将来对 [[GetOwnProperty]] ( P ) 的所有调用必须返回其 [[Value]]P[[Value]] 特性为SameValue属性描述符
  • 如果 P 的除 [[Writable]][[Value]] 之外的特性可能随时间改变,或者属性可能被删除,那么 P[[Configurable]] 特性必须是 true
  • 如果 [[Writable]] 特性可能从 false 变为 true,那么 [[Configurable]] 特性必须是 true
  • 如果目标是不可扩展的并且 P 是不存在的,那么将来在目标上对 [[GetOwnProperty]] (P) 的所有调用必须将 P 描述为不存在的(即 [[GetOwnProperty]] (P) 必须返回 undefined)。
注意 3

作为第三个不变式的结果,如果属性被描述为数据属性并且它可能随时间返回不同的值,那么 [[Writable]][[Configurable]] 特性中的一个或两个必须是 true,即使没有通过其他基本内部方法暴露改变值的机制。

[[DefineOwnProperty]] ( P, Desc )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置自有属性,那么 [[DefineOwnProperty]] 必须返回 false,除非以下之一:
    1. P 是可写的数据属性。不可配置的可写数据属性可以更改为不可配置的不可写数据属性
    2. Desc 的所有特性都与 P 的特性为SameValue
  • 如果目标是不可扩展的并且 P 是不存在的自有属性,那么 [[DefineOwnProperty]] (P, Desc) 必须返回 false。也就是说,不可扩展的目标对象不能用新属性扩展。

[[HasProperty]] ( P )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置自有数据或访问器属性,那么 [[HasProperty]] 必须返回 true

[[Get]] ( P, Receiver )

  • 正常返回类型是任何ECMAScript 语言类型
  • 如果 P 之前被观察为目标的值为 V 的不可配置、不可写的自有数据属性,那么 [[Get]] 必须返回与 V SameValue 相同的值。
  • 如果 P 之前被观察为目标的 [[Get]] 特性为 undefined 的不可配置自有访问器属性,那么 [[Get]] 操作必须返回 undefined

[[Set]] ( P, V, Receiver )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置、不可写的自有数据属性,那么 [[Set]] 必须返回 false,除非 VP[[Value]] 特性为SameValue
  • 如果 P 之前被观察为目标的 [[Set]] 特性为 undefined 的不可配置自有访问器属性,那么 [[Set]] 操作必须返回 false

[[Delete]] ( P )

  • 正常返回类型是 Boolean。
  • 如果 P 之前被观察为目标的不可配置自有数据或访问器属性,那么 [[Delete]] 必须返回 false

[[OwnPropertyKeys]] ( )

  • 正常返回类型是列表
  • 返回的列表不得包含任何重复条目。
  • 返回的列表的每个元素必须是属性键
  • 返回的列表必须至少包含所有之前被观察到的不可配置自有属性的键。
  • 如果目标是不可扩展的,返回的列表必须只包含使用 [[GetOwnProperty]] 可观察到的目标的所有自有属性的键。

[[Call]] ( )

[[Construct]] ( )

  • 正常返回类型是 Object。
  • 目标也必须有一个 [[Call]] 内部方法。

6.1.7.4 知名内置对象

知名内置对象是被本规范算法明确引用的内置对象,通常具有特定的标识。除非另有说明,每个内置对象实际上对应一组相似的对象,每个一个。

在本规范中,像 %name% 这样的引用意味着与当前关联的、对应于该名称的内置对象。像 %name.a.b% 这样的引用意味着,就像在任何 ECMAScript 代码被评估之前访问内置对象 %name% 的 "a" 属性的值的 "b" 属性一样。当前及其内置对象的确定在9.4中描述。知名内置对象列在表 6中。

表 6:知名内置对象
内置名称 全局名称 ECMAScript 语言关联
%AggregateError% AggregateError AggregateError 构造器20.5.7.1
%Array% Array Array 构造器23.1.1
%ArrayBuffer% ArrayBuffer ArrayBuffer 构造器25.1.4
%ArrayIteratorPrototype% 数组迭代器对象的原型(23.1.5
%AsyncFromSyncIteratorPrototype% 异步-从-同步迭代器对象的原型(27.1.6
%AsyncFunction% 异步函数对象构造器27.7.1
%AsyncGeneratorFunction% 异步生成器函数对象构造器27.4.1
%AsyncGeneratorPrototype% 异步生成器对象的原型(27.6
%AsyncIteratorPrototype% 所有标准内置异步迭代器对象间接继承的对象
%Atomics% Atomics Atomics 对象(25.4
%BigInt% BigInt BigInt 构造器21.2.1
%BigInt64Array% BigInt64Array BigInt64Array 构造器23.2
%BigUint64Array% BigUint64Array BigUint64Array 构造器23.2
%Boolean% Boolean Boolean 构造器20.3.1
%DataView% DataView DataView 构造器25.3.2
%Date% Date Date 构造器21.4.2
%decodeURI% decodeURI decodeURI 函数(19.2.6.1
%decodeURIComponent% decodeURIComponent decodeURIComponent 函数(19.2.6.2
%encodeURI% encodeURI encodeURI 函数(19.2.6.3
%encodeURIComponent% encodeURIComponent encodeURIComponent 函数(19.2.6.4
%Error% Error Error 构造器20.5.1
%eval% eval eval 函数(19.2.1
%EvalError% EvalError EvalError 构造器20.5.5.1
%FinalizationRegistry% FinalizationRegistry FinalizationRegistry 构造器26.2.1
%Float16Array% Float16Array Float16Array 构造器23.2
%Float32Array% Float32Array Float32Array 构造器23.2
%Float64Array% Float64Array Float64Array 构造器23.2
%ForInIteratorPrototype% For-In 迭代器对象的原型(14.7.5.10
%Function% Function Function 构造器20.2.1
%GeneratorFunction% 生成器函数对象构造器27.3.1
%GeneratorPrototype% 生成器对象的原型(27.5
%Int8Array% Int8Array Int8Array 构造器23.2
%Int16Array% Int16Array Int16Array 构造器23.2
%Int32Array% Int32Array Int32Array 构造器23.2
%isFinite% isFinite isFinite 函数(19.2.2
%isNaN% isNaN isNaN 函数(19.2.3
%Iterator% Iterator Iterator 构造器27.1.3.1
%IteratorHelperPrototype% 迭代器辅助对象的原型(27.1.2.1
%JSON% JSON JSON 对象(25.5
%Map% Map Map 构造器24.1.1
%MapIteratorPrototype% Map 迭代器对象的原型(24.1.5
%Math% Math Math 对象(21.3
%Number% Number Number 构造器21.1.1
%Object% Object Object 构造器20.1.1
%parseFloat% parseFloat parseFloat 函数(19.2.4
%parseInt% parseInt parseInt 函数(19.2.5
%Promise% Promise Promise 构造器27.2.3
%Proxy% Proxy Proxy 构造器28.2.1
%RangeError% RangeError RangeError 构造器20.5.5.2
%ReferenceError% ReferenceError ReferenceError 构造器20.5.5.3
%Reflect% Reflect Reflect 对象(28.1
%RegExp% RegExp RegExp 构造器22.2.4
%RegExpStringIteratorPrototype% RegExp 字符串迭代器对象的原型(22.2.9
%Set% Set Set 构造器24.2.2
%SetIteratorPrototype% Set 迭代器对象的原型(24.2.6
%SharedArrayBuffer% SharedArrayBuffer SharedArrayBuffer 构造器25.2.3
%String% String String 构造器22.1.1
%StringIteratorPrototype% 字符串迭代器对象的原型(22.1.5
%Symbol% Symbol Symbol 构造器20.4.1
%SyntaxError% SyntaxError SyntaxError 构造器20.5.5.4
%ThrowTypeError% 一个无条件抛出新的%TypeError%实例的函数对象
%TypedArray% 所有类型化数组构造器的超类(23.2.1
%TypeError% TypeError TypeError 构造器20.5.5.5
%Uint8Array% Uint8Array Uint8Array 构造器23.2
%Uint8ClampedArray% Uint8ClampedArray Uint8ClampedArray 构造器23.2
%Uint16Array% Uint16Array Uint16Array 构造器23.2
%Uint32Array% Uint32Array Uint32Array 构造器23.2
%URIError% URIError URIError 构造器20.5.5.6
%WeakMap% WeakMap WeakMap 构造器24.3.1
%WeakRef% WeakRef WeakRef 构造器26.1.1
%WeakSet% WeakSet WeakSet 构造器24.4.1
%WrapForValidIteratorPrototype% Iterator.from 返回的包装迭代器对象的原型(27.1.3.2.1.1
注意

表 102中的附加条目。

6.2 ECMAScript 规范类型

规范类型对应于在算法中用于描述 ECMAScript 语言构造和ECMAScript 语言类型语义的元值。规范类型包括引用记录列表完成记录属性描述符环境记录抽象闭包数据块。规范类型值是规范工件,不一定对应于 ECMAScript 实现中的任何特定实体。规范类型值可用于描述 ECMAScript 表达式求值的中间结果,但此类值不能存储为对象的属性或 ECMAScript 语言变量的值。

6.2.1 枚举规范类型

枚举是规范内部的值,不能从 ECMAScript 代码直接观察到。枚举使用无衬线字体表示。例如,完成记录[[Type]] 字段取值如 normalreturnthrow。枚举除了名称之外没有其他特征。枚举的名称除了将其与其他枚举区分开来之外没有其他目的,并且不暗示其在上下文中的用法或含义。

6.2.2 列表和记录规范类型

列表类型用于解释 new 表达式、函数调用和其他需要简单有序值列表的算法中参数列表的求值(参见13.3.8)。列表类型的值只是包含各个值的列表元素的有序序列。这些序列可以是任意长度。列表的元素可以使用从 0 开始的索引随机访问。为了方便表示,可以使用类似数组的语法来访问列表元素。例如,arguments[2] 是表示列表 arguments 第 3 个元素的简写。

当算法遍历列表的元素而不指定顺序时,使用的顺序是列表中元素的顺序。

为了在本规范中方便表示,可以使用字面量语法来表达新的列表值。例如,« 1, 2 » 定义了一个有两个元素的列表值,每个元素都初始化为特定值。新的空列表可以表示为 « »。

在本规范中,短语"AB、... 的列表连接"(其中每个参数都是可能为空的列表)表示一个新的列表值,其元素是每个参数的元素(按顺序)的连接(按顺序)。

当应用于字符串列表时,短语"按字典序码元顺序排序"意味着按每个码元的数值排序,直到较短字符串的长度,如果所有都相等,则较短的字符串排在较长的字符串之前,如抽象操作IsLessThan中所述。

记录类型用于描述本规范算法中的数据聚合。记录类型值由一个或多个命名字段组成。每个字段的值是ECMAScript 语言值或规范值。字段名总是用双括号括起来,例如 [[Value]]

为了在本规范中方便表示,可以使用类似对象字面量的语法来表达记录值。例如,{ [[Field1]]: 42, [[Field2]]: false, [[Field3]]: empty } 定义了一个有三个字段的记录值,每个字段都初始化为特定值。字段名顺序不重要。任何未明确列出的字段都被认为是缺失的。

在规范文本和算法中,可以使用点记法来引用记录值的特定字段。例如,如果 R 是前一段中显示的记录,那么 R.[[Field2]] 是"R 中名为 [[Field2]] 的字段"的简写。

常用记录字段组合的模式可以被命名,该名称可以用作字面量记录值的前缀,以标识所描述的特定类型的聚合。例如:PropertyDescriptor { [[Value]]: 42, [[Writable]]: false, [[Configurable]]: true }。

6.2.3 集合和关系规范类型

集合类型用于解释在内存模型中使用的无序元素集合。它不同于同名的 ECMAScript 集合类型。为了消除歧义,ECMAScript 集合的实例在本规范中始终称为"Set 对象"。集合类型的值是元素的简单集合,其中没有元素出现超过一次。元素可以添加到集合中或从集合中移除。集合可以进行并集、交集或相减操作。

关系类型用于解释对集合的约束。关系类型的值是其值域中值的有序对的集合。例如,事件上的关系是事件有序对的集合。对于关系 RR 值域中的两个值 aba R b 是说有序对 (a, b) 是 R 的成员的简写。关系是相对于某些条件的最小关系,当它是满足这些条件的最小关系时。

严格偏序是满足以下条件的关系值 R

  • 对于 R 域中的所有 abc

    • a R a 不成立,并且
    • 如果 a R bb R c,那么 a R c
注意 1

上述两个性质分别称为非反射性和传递性。

严格全序是满足以下条件的关系值 R

  • 对于 R 域中的所有 abc

    • aba R bb R a,并且
    • a R a 不成立,并且
    • 如果 a R bb R c,那么 a R c
注意 2

上述三个性质分别称为完全性、非反射性和传递性。

6.2.4 完成记录规范类型

完成记录规范类型用于解释值和控制流的运行时传播,例如执行非本地控制转移的语句(breakcontinuereturnthrow)的行为。

完成记录具有表 7中定义的字段。

表 7:完成记录字段
字段名 含义
[[Type]] normalbreakcontinuereturnthrow 发生的完成类型。
[[Value]] 完成记录之外的任何值 产生的值。
[[Target]] 一个字符串或 empty 定向控制转移的目标标签。

以下简写术语有时用于指代完成记录。

  • 正常完成指任何 [[Type]] 值为 normal 的完成记录。
  • break 完成指任何 [[Type]] 值为 break 的完成记录。
  • continue 完成指任何 [[Type]] 值为 continue 的完成记录。
  • return 完成指任何 [[Type]] 值为 return 的完成记录。
  • throw 完成指任何 [[Type]] 值为 throw 的完成记录。
  • 突然完成指任何 [[Type]] 值不是 normal 的完成记录。
  • 包含某种类型值的正常完成指在其 [[Value]] 字段中具有该类型值的正常完成。

本规范中定义的可调用对象只返回正常完成或 throw 完成。返回任何其他类型的完成记录被认为是编辑错误。

实现定义的可调用对象必须返回正常完成或 throw 完成。

6.2.4.1 NormalCompletion ( value )

抽象操作 NormalCompletion 接受参数 value(除完成记录之外的任何值)并返回一个正常完成。它在被调用时执行以下步骤:

  1. 返回完成记录 { [[Type]]: normal, [[Value]]: value, [[Target]]: empty }。

6.2.4.2 ThrowCompletion ( value )

抽象操作 ThrowCompletion 接受参数 value(一个ECMAScript 语言值)并返回一个throw 完成。它在被调用时执行以下步骤:

  1. 返回完成记录 { [[Type]]: throw, [[Value]]: value, [[Target]]: empty }。

6.2.4.3 ReturnCompletion ( value )

抽象操作 ReturnCompletion 接受参数 value(一个ECMAScript 语言值)并返回一个return 完成。它在被调用时执行以下步骤:

  1. 返回完成记录 { [[Type]]: return, [[Value]]: value, [[Target]]: empty }。

6.2.4.4 UpdateEmpty ( completionRecord, value )

抽象操作 UpdateEmpty 接受参数 completionRecord(一个完成记录)和 value(除完成记录之外的任何值)并返回一个完成记录。它在被调用时执行以下步骤:

  1. 断言:如果 completionRecordreturn 完成throw 完成,那么 completionRecord.[[Value]] 不是 empty
  2. 如果 completionRecord.[[Value]] 不是 empty,返回 ? completionRecord
  3. 返回完成记录 { [[Type]]: completionRecord.[[Type]], [[Value]]: value, [[Target]]: completionRecord.[[Target]] }。

6.2.5 引用记录规范类型

引用记录类型用于解释诸如 deletetypeof、赋值运算符、super 关键字和其他语言特性的行为。例如,赋值的左操作数应该产生一个引用记录。

引用记录是一个已解析的名称或(可能尚未解析的)属性绑定;其字段由表 8定义。

表 8:引用记录字段
字段名 含义
[[Base]] 一个ECMAScript 语言值、一个环境记录unresolvable 持有绑定的值或环境记录[[Base]]unresolvable 表示绑定无法解析。
[[ReferencedName]] 一个ECMAScript 语言值或一个私有名称 绑定的名称。如果 [[Base]] 值是环境记录,则总是字符串。否则,在执行ToPropertyKey之前,可能是字符串或符号以外的ECMAScript 语言值
[[Strict]] 一个布尔值 如果引用记录起源于严格模式代码,则为 true,否则为 false
[[ThisValue]] 一个ECMAScript 语言值empty 如果不是 empty,则引用记录表示使用 super 关键字表达的属性绑定;它被称为超级引用记录,其 [[Base]] 值永远不会是环境记录。在这种情况下,[[ThisValue]] 字段保存创建引用记录时的 this 值。

本规范中使用以下抽象操作来操作引用记录:

6.2.5.1 IsPropertyReference ( V )

抽象操作 IsPropertyReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[Base]]unresolvable,返回 false
  2. 如果 V.[[Base]]环境记录,返回 false;否则返回 true

6.2.5.2 IsUnresolvableReference ( V )

抽象操作 IsUnresolvableReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[Base]]unresolvable,返回 true;否则返回 false

6.2.5.3 IsSuperReference ( V )

抽象操作 IsSuperReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[ThisValue]] 不是 empty,返回 true;否则返回 false

6.2.5.4 IsPrivateReference ( V )

抽象操作 IsPrivateReference 接受参数 V(一个引用记录)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 V.[[ReferencedName]]私有名称,返回 true;否则返回 false

6.2.5.5 GetValue ( V )

抽象操作 GetValue 接受参数 V(一个引用记录或一个ECMAScript 语言值)并返回一个包含ECMAScript 语言值正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 如果 V 不是引用记录,返回 V
  2. 如果IsUnresolvableReference(V) 是 true,抛出 ReferenceError 异常。
  3. 如果IsPropertyReference(V) 是 true,那么
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. 如果IsPrivateReference(V) 是 true,那么
      1. 返回 ? PrivateGet(baseObj, V.[[ReferencedName]])。
    3. 如果 V.[[ReferencedName]] 不是属性键,那么
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. 返回 ? baseObj.[[Get]](V.[[ReferencedName]], GetThisValue(V))。
  4. 否则,
    1. baseV.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.GetBindingValue(V.[[ReferencedName]], V.[[Strict]])(参见9.1)。
注意

在步骤3.a中可能创建的对象在上述抽象操作和普通对象[[Get]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。

6.2.5.6 PutValue ( V, W )

抽象操作 PutValue 接受参数 V(一个引用记录或一个ECMAScript 语言值)和 W(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 如果 V 不是引用记录,抛出 ReferenceError 异常。
  2. 如果IsUnresolvableReference(V) 是 true,那么
    1. 如果 V.[[Strict]]true,抛出 ReferenceError 异常。
    2. globalObjGetGlobalObject()。
    3. 执行 ? Set(globalObj, V.[[ReferencedName]], W, false)。
    4. 返回 unused
  3. 如果IsPropertyReference(V) 是 true,那么
    1. baseObj 为 ? ToObject(V.[[Base]])。
    2. 如果IsPrivateReference(V) 是 true,那么
      1. 返回 ? PrivateSet(baseObj, V.[[ReferencedName]], W)。
    3. 如果 V.[[ReferencedName]] 不是属性键,那么
      1. V.[[ReferencedName]] 为 ? ToPropertyKey(V.[[ReferencedName]])。
    4. succeeded 为 ? baseObj.[[Set]](V.[[ReferencedName]], W, GetThisValue(V))。
    5. 如果 succeededfalseV.[[Strict]]true,抛出 TypeError 异常。
    6. 返回 unused
  4. 否则,
    1. baseV.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.SetMutableBinding(V.[[ReferencedName]], W, V.[[Strict]])(参见9.1)。
注意

在步骤3.a中可能创建的对象在上述抽象操作和普通对象[[Set]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。

6.2.5.7 GetThisValue ( V )

抽象操作 GetThisValue 接受参数 V(一个引用记录)并返回一个ECMAScript 语言值。它在被调用时执行以下步骤:

  1. 断言IsPropertyReference(V) 是 true
  2. 如果IsSuperReference(V) 是 true,返回 V.[[ThisValue]];否则返回 V.[[Base]]

6.2.5.8 InitializeReferencedBinding ( V, W )

抽象操作 InitializeReferencedBinding 接受参数 V(一个引用记录)和 W(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个突然完成。它在被调用时执行以下步骤:

  1. 断言IsUnresolvableReference(V) 是 false
  2. baseV.[[Base]]
  3. 断言base环境记录
  4. 返回 ? base.InitializeBinding(V.[[ReferencedName]], W)。

6.2.5.9 MakePrivateReference ( baseValue, privateIdentifier )

抽象操作 MakePrivateReference 接受参数 baseValue(一个ECMAScript 语言值)和 privateIdentifier(一个字符串)并返回一个引用记录。它在被调用时执行以下步骤:

  1. privateEnv运行执行上下文的 PrivateEnvironment。
  2. 断言privateEnv 不是 null
  3. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  4. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: privateName, [[Strict]]: true, [[ThisValue]]: empty }。

6.2.6 属性描述符规范类型

属性描述符类型用于解释对象属性特性的操作和具体化。属性描述符是一个具有零个或多个字段的记录,其中每个字段的名称是一个特性名称,其值是6.1.7.1中指定的相应特性值。本规范中用于标记属性描述符记录字面量描述的模式名称是"PropertyDescriptor"。

属性描述符值可以根据某些字段的存在或使用进一步分类为数据属性描述符和访问器属性描述符。数据属性描述符是包含名为 [[Value]][[Writable]] 的任何字段的描述符。访问器属性描述符是包含名为 [[Get]][[Set]] 的任何字段的描述符。任何属性描述符都可以有名为 [[Enumerable]][[Configurable]] 的字段。属性描述符值不能既是数据属性描述符又是访问器属性描述符;但是,它可以两者都不是(在这种情况下它是通用属性描述符)。完全填充的属性描述符是访问器属性描述符或数据属性描述符,并且具有表 3中定义的所有相应字段。

本规范中使用以下抽象操作来操作属性描述符值:

6.2.6.1 IsAccessorDescriptor ( Desc )

抽象操作 IsAccessorDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 Desc[[Get]] 字段,返回 true
  2. 如果 Desc[[Set]] 字段,返回 true
  3. 返回 false

6.2.6.2 IsDataDescriptor ( Desc )

抽象操作 IsDataDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 Desc[[Value]] 字段,返回 true
  2. 如果 Desc[[Writable]] 字段,返回 true
  3. 返回 false

6.2.6.3 IsGenericDescriptor ( Desc )

抽象操作 IsGenericDescriptor 接受参数 Desc(一个属性描述符)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果IsAccessorDescriptor(Desc) 是 true,返回 false
  2. 如果IsDataDescriptor(Desc) 是 true,返回 false
  3. 返回 true

6.2.6.4 FromPropertyDescriptor ( Desc )

抽象操作 FromPropertyDescriptor 接受参数 Desc(一个属性描述符undefined)并返回一个对象或 undefined。它在被调用时执行以下步骤:

  1. 如果 Descundefined,返回 undefined
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言obj 是一个可扩展的普通对象,没有自有属性。
  4. 如果 Desc[[Value]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "value", Desc.[[Value]])。
  5. 如果 Desc[[Writable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "writable", Desc.[[Writable]])。
  6. 如果 Desc[[Get]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "get", Desc.[[Get]])。
  7. 如果 Desc[[Set]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "set", Desc.[[Set]])。
  8. 如果 Desc[[Enumerable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "enumerable", Desc.[[Enumerable]])。
  9. 如果 Desc[[Configurable]] 字段,那么
    1. 执行 ! CreateDataPropertyOrThrow(obj, "configurable", Desc.[[Configurable]])。
  10. 返回 obj

6.2.6.5 ToPropertyDescriptor ( Obj )

抽象操作 ToPropertyDescriptor 接受参数 Obj(一个ECMAScript 语言值)并返回一个包含属性描述符正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 Obj 不是对象,抛出 TypeError 异常。
  2. desc 为一个新的属性描述符,初始时没有字段。
  3. hasEnumerable 为 ? HasProperty(Obj, "enumerable")。
  4. 如果 hasEnumerabletrue,那么
    1. enumerableToBoolean(? Get(Obj, "enumerable"))。
    2. desc.[[Enumerable]]enumerable
  5. hasConfigurable 为 ? HasProperty(Obj, "configurable")。
  6. 如果 hasConfigurabletrue,那么
    1. configurableToBoolean(? Get(Obj, "configurable"))。
    2. desc.[[Configurable]]configurable
  7. hasValue 为 ? HasProperty(Obj, "value")。
  8. 如果 hasValuetrue,那么
    1. value 为 ? Get(Obj, "value")。
    2. desc.[[Value]]value
  9. hasWritable 为 ? HasProperty(Obj, "writable")。
  10. 如果 hasWritabletrue,那么
    1. writableToBoolean(? Get(Obj, "writable"))。
    2. desc.[[Writable]]writable
  11. hasGet 为 ? HasProperty(Obj, "get")。
  12. 如果 hasGettrue,那么
    1. getter 为 ? Get(Obj, "get")。
    2. 如果IsCallable(getter) 是 falsegetter 不是 undefined,抛出 TypeError 异常。
    3. desc.[[Get]]getter
  13. hasSet 为 ? HasProperty(Obj, "set")。
  14. 如果 hasSettrue,那么
    1. setter 为 ? Get(Obj, "set")。
    2. 如果IsCallable(setter) 是 falsesetter 不是 undefined,抛出 TypeError 异常。
    3. desc.[[Set]]setter
  15. 如果 desc[[Get]] 字段或 desc[[Set]] 字段,那么
    1. 如果 desc[[Value]] 字段或 desc[[Writable]] 字段,抛出 TypeError 异常。
  16. 返回 desc

6.2.6.6 CompletePropertyDescriptor ( Desc )

抽象操作 CompletePropertyDescriptor 接受参数 Desc(一个属性描述符)并返回 unused。它在被调用时执行以下步骤:

  1. like记录 { [[Value]]: undefined, [[Writable]]: false, [[Get]]: undefined, [[Set]]: undefined, [[Enumerable]]: false, [[Configurable]]: false }。
  2. 如果IsGenericDescriptor(Desc) 是 trueIsDataDescriptor(Desc) 是 true,那么
    1. 如果 Desc 没有 [[Value]] 字段,设 Desc.[[Value]]like.[[Value]]
    2. 如果 Desc 没有 [[Writable]] 字段,设 Desc.[[Writable]]like.[[Writable]]
  3. 否则,
    1. 如果 Desc 没有 [[Get]] 字段,设 Desc.[[Get]]like.[[Get]]
    2. 如果 Desc 没有 [[Set]] 字段,设 Desc.[[Set]]like.[[Set]]
  4. 如果 Desc 没有 [[Enumerable]] 字段,设 Desc.[[Enumerable]]like.[[Enumerable]]
  5. 如果 Desc 没有 [[Configurable]] 字段,设 Desc.[[Configurable]]like.[[Configurable]]
  6. 返回 unused

6.2.7 环境记录规范类型

环境记录类型用于解释嵌套函数和块中名称解析的行为。此类型及其操作在9.1中定义。

6.2.8 抽象闭包规范类型

抽象闭包规范类型用于引用算法步骤以及一系列值。抽象闭包是元值,使用函数调用样式调用,例如 closure(arg1, arg2)。与抽象操作类似,调用执行抽象闭包描述的算法步骤。

在创建抽象闭包的算法步骤中,值使用动词"capture"后跟别名列表来捕获。当创建抽象闭包时,它捕获当时与每个别名关联的值。在指定调用抽象闭包时要执行的算法的步骤中,每个捕获的值都通过用于捕获该值的别名来引用。

如果抽象闭包返回完成记录,该完成记录必须是正常完成throw 完成

抽象闭包作为其他算法的一部分内联创建,如以下示例所示。

  1. addend 为 41。
  2. closure 为一个新的抽象闭包,参数为 (x),捕获 addend 并在调用时执行以下步骤:
    1. 返回 x + addend
  3. valclosure(1)。
  4. 断言val 是 42。

6.2.9 数据块

数据块规范类型用于描述一个不同且可变的字节大小(8位)数值序列。字节值闭区间从 0 到 255 的整数。数据块值使用固定数量的字节创建,每个字节的初始值为 0。

为了在本规范中表示方便,可以使用类似数组的语法来访问数据块值的各个字节。此表示法将数据块值表示为基于 0 的整数索引字节序列。例如,如果 db 是一个 5 字节的数据块值,则可以使用 db[2] 来访问其第 3 个字节。

驻留在内存中且可以被多个代理并发引用的数据块被指定为共享数据块。共享数据块具有一个标识(用于相等性测试共享数据块值的目的),该标识是地址无关的:它不与块在任何进程中映射到的虚拟地址绑定,而是与块表示的内存位置集合绑定。两个数据块仅在它们包含的位置集合相等时才相等;否则,它们不相等,且它们包含的位置集合的交集为空。最后,共享数据块可以与数据块区分开来。

共享数据块的语义通过内存模型使用共享数据块事件定义。下面的抽象操作引入共享数据块事件,并作为评估语义和内存模型事件语义之间的接口。这些事件形成一个候选执行内存模型对其起过滤器作用。请参考内存模型以获取完整语义。

共享数据块事件内存模型中定义的记录建模。

本规范中使用以下抽象操作来操作数据块值:

6.2.9.1 CreateByteDataBlock ( size )

抽象操作 CreateByteDataBlock 接受参数 size(一个非负整数)并返回一个包含数据块正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 size > 253 - 1,抛出 RangeError 异常。
  2. db 为一个新的数据块值,由 size 个字节组成。如果无法创建这样的数据块,抛出 RangeError 异常。
  3. db 的所有字节设置为 0。
  4. 返回 db

6.2.9.2 CreateSharedByteDataBlock ( size )

抽象操作 CreateSharedByteDataBlock 接受参数 size(一个非负整数)并返回一个包含共享数据块正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. db 为一个新的共享数据块值,由 size 个字节组成。如果无法创建这样的共享数据块,抛出 RangeError 异常。
  2. execution周围代理代理记录[[CandidateExecution]] 字段。
  3. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的代理事件记录
  4. zero 为 « 0 »。
  5. 对于 db 的每个索引 i,执行
    1. WriteSharedMemory { [[Order]]: init, [[NoTear]]: true, [[Block]]: db, [[ByteIndex]]: i, [[ElementSize]]: 1, [[Payload]]: zero } 追加到 eventsRecord.[[EventList]]
  6. 返回 db

6.2.9.3 CopyDataBlockBytes ( toBlock, toIndex, fromBlock, fromIndex, count )

抽象操作 CopyDataBlockBytes 接受参数 toBlock(一个数据块或一个共享数据块)、toIndex(一个非负整数)、fromBlock(一个数据块或一个共享数据块)、fromIndex(一个非负整数)和 count(一个非负整数)并返回 unused。它在被调用时执行以下步骤:

  1. 断言fromBlocktoBlock 是不同的值。
  2. fromSizefromBlock 中的字节数。
  3. 断言fromIndex + countfromSize
  4. toSizetoBlock 中的字节数。
  5. 断言toIndex + counttoSize
  6. 重复,当 count > 0 时,
    1. 如果 fromBlock共享数据块,那么
      1. execution周围代理代理记录[[CandidateExecution]] 字段。
      2. eventsRecordexecution.[[EventsRecords]][[AgentSignifier]]AgentSignifier() 的代理事件记录
      3. bytes 为一个列表,其唯一元素是一个非确定性选择的字节值
      4. 注意:在实现中,bytes 是底层硬件上非原子读取指令的结果。非确定性是内存模型对描述弱一致性硬件可观察行为的语义规定。
      5. readEventReadSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: fromBlock, [[ByteIndex]]: fromIndex, [[ElementSize]]: 1 }。
      6. readEvent 追加到 eventsRecord.[[EventList]]
      7. 选择值记录 { [[Event]]: readEvent, [[ChosenValue]]: bytes } 追加到 execution.[[ChosenValues]]
      8. 如果 toBlock共享数据块,那么
        1. WriteSharedMemory { [[Order]]: unordered, [[NoTear]]: true, [[Block]]: toBlock, [[ByteIndex]]: toIndex, [[ElementSize]]: 1, [[Payload]]: bytes } 追加到 eventsRecord.[[EventList]]
      9. 否则,
        1. toBlock[toIndex] 为 bytes[0]。
    2. 否则,
      1. 断言toBlock 不是共享数据块
      2. toBlock[toIndex] 为 fromBlock[fromIndex]。
    3. toIndextoIndex + 1。
    4. fromIndexfromIndex + 1。
    5. countcount - 1。
  7. 返回 unused

6.2.10 PrivateElement 规范类型

PrivateElement 类型是一个记录,用于私有类字段、方法和访问器的规范。虽然属性描述符不用于私有元素,但私有字段的行为类似于不可配置、不可枚举、可写的数据属性,私有方法的行为类似于不可配置、不可枚举、不可写的数据属性,私有访问器的行为类似于不可配置、不可枚举的访问器属性

PrivateElement 类型的值是记录值,其字段由表 9定义。这些值被称为PrivateElement

表 9:PrivateElement 字段
字段名 出现该字段的 [[Kind]] 字段值 含义
[[Key]] 全部 一个私有名称 字段、方法或访问器的名称。
[[Kind]] 全部 fieldmethodaccessor 元素的类型。
[[Value]] fieldmethod 一个ECMAScript 语言值 字段的值。
[[Get]] accessor 一个函数对象undefined 私有访问器的 getter。
[[Set]] accessor 一个函数对象undefined 私有访问器的 setter。

6.2.11 ClassFieldDefinition 记录规范类型

ClassFieldDefinition 类型是一个记录,用于类字段的规范。

ClassFieldDefinition 类型的值是记录值,其字段由表 10定义。这些值被称为ClassFieldDefinition 记录

表 10:ClassFieldDefinition 记录字段
字段名 含义
[[Name]] 一个私有名称、字符串或符号 字段的名称。
[[Initializer]] 一个 ECMAScript 函数对象empty 字段的初始化器(如果有)。

6.2.12 私有名称

私有名称规范类型用于描述一个全局唯一值(即使与其他私有名称在其他方面无法区分,该值也与任何其他私有名称不同),它表示私有类元素(字段、方法或访问器)的键。每个私有名称都有一个关联的不可变 [[Description]],它是一个字符串值。私有名称可以通过PrivateFieldAddPrivateMethodOrAccessorAdd安装在任何 ECMAScript 对象上,然后使用PrivateGetPrivateSet进行读取或写入。

6.2.13 ClassStaticBlockDefinition 记录规范类型

ClassStaticBlockDefinition 记录是一个记录值,用于封装类静态初始化块的可执行代码。

ClassStaticBlockDefinition 记录具有表 11中列出的字段。

表 11:ClassStaticBlockDefinition 记录字段
字段名 含义
[[BodyFunction]] 一个 ECMAScript 函数对象 在类的静态初始化期间要调用的函数对象

7 抽象操作

这些操作不是 ECMAScript 语言的一部分;定义它们仅是为了帮助说明 ECMAScript 语言的语义。其他更专门的抽象操作在本规范中都有定义。

7.1 类型转换

ECMAScript 语言根据需要隐式执行自动类型转换。为了阐明某些构造的语义,定义一组转换抽象操作是有用的。转换抽象操作是多态的;它们可以接受任何ECMAScript 语言类型的值。但这些操作不使用其他规范类型。

BigInt 类型在 ECMAScript 语言中没有隐式转换;程序员必须显式调用 BigInt 来将值从其他类型转换。

7.1.1 ToPrimitive ( input [ , preferredType ] )

抽象操作 ToPrimitive 接受参数 input(一个ECMAScript 语言值)和可选参数 preferredTypestringnumber)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。它将其 input 参数转换为非对象类型。如果对象能够转换为多个原始类型,它可以使用可选提示 preferredType 来偏向该类型。它在被调用时执行以下步骤:

  1. 如果 input 是对象,那么
    1. exoticToPrim 为 ? GetMethod(input, %Symbol.toPrimitive%)。
    2. 如果 exoticToPrim 不是 undefined,那么
      1. 如果 preferredType 不存在,那么
        1. hint"default"
      2. 否则如果 preferredTypestring,那么
        1. hint"string"
      3. 否则,
        1. 断言preferredTypenumber
        2. hint"number"
      4. result 为 ? Call(exoticToPrim, input, « hint »)。
      5. 如果 result 不是对象,返回 result
      6. 抛出 TypeError 异常。
    3. 如果 preferredType 不存在,设 preferredTypenumber
    4. 返回 ? OrdinaryToPrimitive(input, preferredType)。
  2. 返回 input
注意

当调用 ToPrimitive 时不带提示,那么它通常表现为提示是 number。但是,对象可以通过定义 %Symbol.toPrimitive% 方法来覆盖此行为。在本规范中定义的对象中,只有 Date(参见 21.4.4.45)和 Symbol 对象(参见 20.4.3.5)覆盖默认的 ToPrimitive 行为。Date 将提示的缺失视为提示是 string

7.1.1.1 OrdinaryToPrimitive ( O, hint )

抽象操作 OrdinaryToPrimitive 接受参数 O(一个对象)和 hintstringnumber)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 hintstring,那么
    1. methodNames 为 « "toString", "valueOf" »。
  2. 否则,
    1. methodNames 为 « "valueOf", "toString" »。
  3. 对于 methodNames 的每个元素 name,执行
    1. method 为 ? Get(O, name)。
    2. 如果 IsCallable(method) 是 true,那么
      1. result 为 ? Call(method, O)。
      2. 如果 result 不是对象,返回 result
  4. 抛出 TypeError 异常。

7.1.2 ToBoolean ( argument )

抽象操作 ToBoolean 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它将 argument 转换为布尔类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是布尔值,返回 argument
  2. 如果 argumentundefinednull+0𝔽-0𝔽NaN0 或空字符串之一,返回 false
  3. 注意:此步骤在章节 B.3.6.1 中被替换。
  4. 返回 true

7.1.3 ToNumeric ( value )

抽象操作 ToNumeric 接受参数 value(一个ECMAScript 语言值)并返回一个包含数字或 BigInt 的正常完成,或一个throw 完成。它返回转换为数字或 BigInt 的 value。它在被调用时执行以下步骤:

  1. primValue 为 ? ToPrimitive(value, number)。
  2. 如果 primValue 是 BigInt,返回 primValue
  3. 返回 ? ToNumber(primValue)。

7.1.4 ToNumber ( argument )

抽象操作 ToNumber 接受参数 argument(一个ECMAScript 语言值)并返回一个包含数字的正常完成或一个throw 完成。它将 argument 转换为数字类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是数字,返回 argument
  2. 如果 argument 是符号或 BigInt,抛出 TypeError 异常。
  3. 如果 argumentundefined,返回 NaN
  4. 如果 argumentnullfalse,返回 +0𝔽
  5. 如果 argumenttrue,返回 1𝔽
  6. 如果 argument 是字符串,返回 StringToNumber(argument)。
  7. 断言argument 是对象
  8. primValue 为 ? ToPrimitive(argument, number)。
  9. 断言primValue 不是对象
  10. 返回 ? ToNumber(primValue)。

7.1.4.1 ToNumber 应用于字符串类型

抽象操作 StringToNumber 指定如何使用以下语法将字符串值转换为数字值。

语法

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

所有未在上面明确定义的语法符号都具有数字字面量词法语法中使用的定义(12.9.3

注意

应注意 StringNumericLiteralNumericLiteral 语法之间的一些差异:

7.1.4.1.1 StringToNumber ( str )

抽象操作 StringToNumber 接受参数 str(一个字符串)并返回一个数字。它在被调用时执行以下步骤:

  1. literalParseText(str, StringNumericLiteral)。
  2. 如果 literal 是错误的列表,返回 NaN
  3. 返回 literalStringNumericValue

7.1.4.1.2 运行时语义:StringNumericValue

语法导向操作 StringNumericValue 不接受参数并返回一个数字。

注意

StringNumericLiteral 到数字值的转换总体上类似于确定 NumericLiteralNumericValue(参见 12.9.3),但一些细节不同。

它在以下产生式上分段定义:

StringNumericLiteral ::: StrWhiteSpace opt
  1. 返回 +0𝔽
StringNumericLiteral ::: StrWhiteSpace opt StrNumericLiteral StrWhiteSpace opt
  1. 返回 StrNumericLiteralStringNumericValue
StrNumericLiteral ::: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
StrDecimalLiteral ::: - StrUnsignedDecimalLiteral
  1. aStrUnsignedDecimalLiteralStringNumericValue
  2. 如果 a+0𝔽,返回 -0𝔽
  3. 返回 -a
StrUnsignedDecimalLiteral ::: Infinity
  1. 返回 +∞𝔽
StrUnsignedDecimalLiteral ::: DecimalDigits . DecimalDigits opt ExponentPart opt
  1. a 为第一个 DecimalDigits 的 MV。
  2. 如果第二个 DecimalDigits 存在,那么
    1. b 为第二个 DecimalDigits 的 MV。
    2. n 为第二个 DecimalDigits 中的代码点数。
  3. 否则,
    1. b 为 0。
    2. n 为 0。
  4. 如果 ExponentPart 存在,设 eExponentPart 的 MV。否则,设 e 为 0。
  5. 返回 RoundMVResult((a + (b × 10-n)) × 10e)。
StrUnsignedDecimalLiteral ::: . DecimalDigits ExponentPart opt
  1. bDecimalDigits 的 MV。
  2. 如果 ExponentPart 存在,设 eExponentPart 的 MV。否则,设 e 为 0。
  3. nDecimalDigits 中的代码点数。
  4. 返回 RoundMVResult(b × 10e - n)。
StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPart opt
  1. aDecimalDigits 的 MV。
  2. 如果 ExponentPart 存在,设 eExponentPart 的 MV。否则,设 e 为 0。
  3. 返回 RoundMVResult(a × 10e)。

7.1.4.1.3 RoundMVResult ( n )

抽象操作 RoundMVResult 接受参数 n(一个数学值)并返回一个数字。它以实现定义的方式将 n 转换为数字。对于此抽象操作的目的,如果数字不是零或其左侧有非零数字且其右侧有非零数字,则该数字是有效的。对于此抽象操作的目的,数学值表示法的"表示的数学值"是数学值的"十进制表示"的逆。它在被调用时执行以下步骤:

  1. 如果 n 的十进制表示有 20 或更少的有效数字,返回 𝔽(n)。
  2. option1 为将 n 的十进制表示中第 20 位后的每个有效数字替换为 0 数字的结果表示的数学值
  3. option2 为将 n 的十进制表示中第 20 位后的每个有效数字替换为 0 数字,然后在第 20 位增加 1(根据需要进位)的结果表示的数学值
  4. chosenoption1option2实现定义选择。
  5. 返回 𝔽(chosen)。

7.1.5 ToIntegerOrInfinity ( argument )

抽象操作 ToIntegerOrInfinity 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数、+∞ 或 -∞ 的正常完成或一个throw 完成。它将 argument 转换为表示其数字值的整数(小数部分被截断),或者当该数字值是无限时转换为 +∞ 或 -∞。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 numberNaN+0𝔽-0𝔽 之一,返回 0。
  3. 如果 number+∞𝔽,返回 +∞。
  4. 如果 number-∞𝔽,返回 -∞。
  5. 返回 truncate((number))。
注意
对于任何值 x𝔽(ToIntegerOrInfinity(x)) 永远不会返回 -0𝔽。小数部分的截断在将 x 转换为数学值之后执行。

7.1.6 ToInt32 ( argument )

抽象操作 ToInt32 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 𝔽(-231) 到 𝔽(231 - 1) 的闭区间内的 232整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int32bitint modulo 232
  5. 如果 int32bit ≥ 231,返回 𝔽(int32bit - 232);否则返回 𝔽(int32bit)。
注意

根据 ToInt32 的上述定义:

  • ToInt32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
  • 对于所有值 x,ToInt32(ToUint32(x)) 与 ToInt32(x) 是相同的值。(为了保持这个后续属性,+∞𝔽-∞𝔽 被映射为 +0𝔽。)
  • ToInt32 将 -0𝔽 映射为 +0𝔽

7.1.7 ToUint32 ( argument )

抽象操作 ToUint32 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽𝔽(232 - 1) 的闭区间内的 232整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int32bitint modulo 232
  5. 返回 𝔽(int32bit)。
注意

根据 ToUint32 的上述定义:

  • 步骤 5 是 ToUint32 和 ToInt32 之间的唯一区别。
  • ToUint32 抽象操作是幂等的:如果应用于它产生的结果,第二次应用不会改变该值。
  • 对于所有值 x,ToUint32(ToInt32(x)) 与 ToUint32(x) 是相同的值。(为了保持这个后续属性,+∞𝔽-∞𝔽 被映射为 +0𝔽。)
  • ToUint32 将 -0𝔽 映射为 +0𝔽

7.1.8 ToInt16 ( argument )

抽象操作 ToInt16 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 𝔽(-215) 到 𝔽(215 - 1) 的闭区间内的 216整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int16bitint modulo 216
  5. 如果 int16bit ≥ 215,返回 𝔽(int16bit - 216);否则返回 𝔽(int16bit)。

7.1.9 ToUint16 ( argument )

抽象操作 ToUint16 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽𝔽(216 - 1) 的闭区间内的 216整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int16bitint modulo 216
  5. 返回 𝔽(int16bit)。
注意

根据 ToUint16 的上述定义:

  • 在步骤 4 中将 232 替换为 216ToUint32 和 ToUint16 之间的唯一区别。
  • ToUint16 将 -0𝔽 映射为 +0𝔽

7.1.10 ToInt8 ( argument )

抽象操作 ToInt8 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 -128𝔽127𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int8bitint modulo 28
  5. 如果 int8bit ≥ 27,返回 𝔽(int8bit - 28);否则返回 𝔽(int8bit)。

7.1.11 ToUint8 ( argument )

抽象操作 ToUint8 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 转换为从 +0𝔽255𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 number 不是有限的number+0𝔽-0𝔽,返回 +0𝔽
  3. inttruncate((number))。
  4. int8bitint modulo 28
  5. 返回 𝔽(int8bit)。

7.1.12 ToUint8Clamp ( argument )

抽象操作 ToUint8Clamp 接受参数 argument(一个ECMAScript 语言值)并返回一个包含整数数字正常完成或一个throw 完成。它将 argument 限制并舍入为从 +0𝔽255𝔽闭区间内的 28整数数字值之一。它在被调用时执行以下步骤:

  1. number 为 ? ToNumber(argument)。
  2. 如果 numberNaN,返回 +0𝔽
  3. mvnumber扩展数学值
  4. clamped 为将 mv 限制在 0 和 255 之间的结果。
  5. ffloor(clamped)。
  6. 如果 clamped < f + 0.5,返回 𝔽(f)。
  7. 如果 clamped > f + 0.5,返回 𝔽(f + 1)。
  8. 如果 f 是偶数,返回 𝔽(f)。否则,返回 𝔽(f + 1)。
注意

与大多数其他 ECMAScript 整数转换操作不同,ToUint8Clamp 舍入而不是截断非整数值。它还使用"舍入到最近偶数"的平分策略,这与 Math.round 的"舍入到更大值"平分策略不同。

7.1.13 ToBigInt ( argument )

抽象操作 ToBigInt 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为 BigInt 值,或者如果需要从数字进行隐式转换则抛出异常。它在被调用时执行以下步骤:

  1. prim 为 ? ToPrimitive(argument, number)。
  2. 返回 prim表 12 中对应的值。
表 12:BigInt 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 如果 primtrue 返回 1n,如果 primfalse 返回 0n
BigInt 返回 prim
Number 抛出 TypeError 异常。
String
  1. nStringToBigInt(prim)。
  2. 如果 nundefined,抛出 SyntaxError 异常。
  3. 返回 n
Symbol 抛出 TypeError 异常。

7.1.14 StringToBigInt ( str )

抽象操作 StringToBigInt 接受参数 str(一个字符串)并返回一个 BigInt 或 undefined。它在被调用时执行以下步骤:

  1. literalParseText(str, StringIntegerLiteral)。
  2. 如果 literal 是错误的列表,返回 undefined
  3. mvliteral 的 MV。
  4. 断言mv 是一个整数
  5. 返回 (mv)。

7.1.14.1 StringIntegerLiteral 语法

StringToBigInt 使用以下语法。

语法

StringIntegerLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrIntegerLiteral StrWhiteSpaceopt StrIntegerLiteral ::: SignedInteger[~Sep] NonDecimalIntegerLiteral[~Sep]

7.1.14.2 运行时语义:MV

7.1.15 ToBigInt64 ( argument )

抽象操作 ToBigInt64 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为从 (-263) 到 (263 - 1) 的闭区间内的 264 个 BigInt 值之一。它在被调用时执行以下步骤:

  1. n 为 ? ToBigInt(argument)。
  2. int64bit(n) modulo 264
  3. 如果 int64bit ≥ 263,返回 (int64bit - 264);否则返回 (int64bit)。

7.1.16 ToBigUint64 ( argument )

抽象操作 ToBigUint64 接受参数 argument(一个ECMAScript 语言值)并返回一个包含 BigInt 的正常完成或一个throw 完成。它将 argument 转换为从 0(264 - 1) 的闭区间内的 264 个 BigInt 值之一。它在被调用时执行以下步骤:

  1. n 为 ? ToBigInt(argument)。
  2. int64bit(n) modulo 264
  3. 返回 (int64bit)。

7.1.17 ToString ( argument )

抽象操作 ToString 接受参数 argument(一个ECMAScript 语言值)并返回一个包含字符串的正常完成或一个throw 完成。它将 argument 转换为字符串类型的值。它在被调用时执行以下步骤:

  1. 如果 argument 是字符串,返回 argument
  2. 如果 argument 是符号,抛出 TypeError 异常。
  3. 如果 argumentundefined,返回 "undefined"
  4. 如果 argumentnull,返回 "null"
  5. 如果 argumenttrue,返回 "true"
  6. 如果 argumentfalse,返回 "false"
  7. 如果 argument 是数字,返回 Number::toString(argument, 10)。
  8. 如果 argument 是 BigInt,返回 BigInt::toString(argument, 10)。
  9. 断言argument 是对象
  10. primValue 为 ? ToPrimitive(argument, string)。
  11. 断言primValue 不是对象
  12. 返回 ? ToString(primValue)。

7.1.18 ToObject ( argument )

抽象操作 ToObject 接受参数 argument(一个ECMAScript 语言值)并返回一个包含对象的正常完成或一个throw 完成。它根据表 13argument 转换为对象类型的值:

表 13:ToObject 转换
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 返回一个新的布尔对象,其 [[BooleanData]] 内部槽设置为 argument。有关布尔对象的描述,请参见 20.3
Number 返回一个新的数字对象,其 [[NumberData]] 内部槽设置为 argument。有关数字对象的描述,请参见 21.1
String 返回一个新的字符串对象,其 [[StringData]] 内部槽设置为 argument。有关字符串对象的描述,请参见 22.1
Symbol 返回一个新的符号对象,其 [[SymbolData]] 内部槽设置为 argument。有关符号对象的描述,请参见 20.4
BigInt 返回一个新的 BigInt 对象,其 [[BigIntData]] 内部槽设置为 argument。有关 BigInt 对象的描述,请参见 21.2
Object 返回 argument

7.1.19 ToPropertyKey ( argument )

抽象操作 ToPropertyKey 接受参数 argument(一个ECMAScript 语言值)并返回一个包含属性键正常完成或一个throw 完成。它将 argument 转换为可用作属性键的值。它在被调用时执行以下步骤:

  1. key 为 ? ToPrimitive(argument, string)。
  2. 如果 key 是符号,那么
    1. 返回 key
  3. 返回 ! ToString(key)。

7.1.20 ToLength ( argument )

抽象操作 ToLength 接受参数 argument(一个ECMAScript 语言值)并返回一个包含非负整数数字正常完成或一个throw 完成。它将 argument 限制并截断为适合用作类数组对象长度的非负整数数字。它在被调用时执行以下步骤:

  1. len 为 ? ToIntegerOrInfinity(argument)。
  2. 如果 len ≤ 0,返回 +0𝔽
  3. 返回 𝔽(min(len, 253 - 1))。

7.1.21 CanonicalNumericIndexString ( argument )

抽象操作 CanonicalNumericIndexString 接受参数 argument(一个字符串)并返回一个数字或 undefined。如果 argument"-0" 或完全匹配某个数字值 nToString(n),它返回相应的数字值。否则,它返回 undefined。它在被调用时执行以下步骤:

  1. 如果 argument"-0",返回 -0𝔽
  2. n 为 ! ToNumber(argument)。
  3. 如果 ! ToString(n) 是 argument,返回 n
  4. 返回 undefined

规范数字字符串是 CanonicalNumericIndexString 抽象操作不返回 undefined 的任何字符串。

7.1.22 ToIndex ( value )

抽象操作 ToIndex 接受参数 value(一个ECMAScript 语言值)并返回一个包含非负整数正常完成或一个throw 完成。它将 value 转换为整数,如果该整数非负且对应于整数索引则返回该整数。否则,它抛出异常。它在被调用时执行以下步骤:

  1. integer 为 ? ToIntegerOrInfinity(value)。
  2. 如果 integer 不在从 0 到 253 - 1 的闭区间内,抛出 RangeError 异常。
  3. 返回 integer

7.2 测试和比较操作

7.2.1 RequireObjectCoercible ( argument )

抽象操作 RequireObjectCoercible 接受参数 argument(一个ECMAScript 语言值)并返回一个包含ECMAScript 语言值正常完成或一个throw 完成。如果 argument 是不能使用 ToObject 转换为对象的值,它抛出错误。它由表 14 定义:

表 14:RequireObjectCoercible 结果
参数类型 结果
Undefined 抛出 TypeError 异常。
Null 抛出 TypeError 异常。
Boolean 返回 argument
Number 返回 argument
String 返回 argument
Symbol 返回 argument
BigInt 返回 argument
Object 返回 argument

7.2.2 IsArray ( argument )

抽象操作 IsArray 接受参数 argument(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument数组异质对象,返回 true
  3. 如果 argument代理异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(argument)。
    2. proxyTargetargument.[[ProxyTarget]]
    3. 返回 ? IsArray(proxyTarget)。
  4. 返回 false

7.2.3 IsCallable ( argument )

抽象操作 IsCallable 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它确定 argument 是否是具有 [[Call]] 内部方法的可调用函数。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument[[Call]] 内部方法,返回 true
  3. 返回 false

7.2.4 IsConstructor ( argument )

抽象操作 IsConstructor 接受参数 argument(一个ECMAScript 语言值)并返回一个布尔值。它确定 argument 是否是具有 [[Construct]] 内部方法的函数对象。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. 如果 argument[[Construct]] 内部方法,返回 true
  3. 返回 false

7.2.5 IsExtensible ( O )

抽象操作 IsExtensible 接受参数 O(一个对象)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定是否可以向 O 添加其他属性。它在被调用时执行以下步骤:

  1. 返回 ? O.[[IsExtensible]]()。

7.2.6 IsRegExp ( argument )

抽象操作 IsRegExp 接受参数 argument(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 argument 不是对象,返回 false
  2. matcher 为 ? Get(argument, %Symbol.match%)。
  3. 如果 matcher 不是 undefined,返回 ToBoolean(matcher)。
  4. 如果 argument[[RegExpMatcher]] 内部槽,返回 true
  5. 返回 false

7.2.7 静态语义:IsStringWellFormedUnicode ( string )

抽象操作 IsStringWellFormedUnicode 接受参数 string(一个字符串)并返回一个布尔值。它将 string 解释为 UTF-16 编码代码点的序列,如6.1.4 中所述,并确定它是否是一个格式正确的 UTF-16 序列。它在被调用时执行以下步骤:

  1. lenstring 的长度。
  2. k 为 0。
  3. 重复,当 k < len 时,
    1. cpCodePointAt(string, k)。
    2. 如果 cp.[[IsUnpairedSurrogate]]true,返回 false
    3. kk + cp.[[CodeUnitCount]]
  4. 返回 true

7.2.8 SameType ( x, y )

抽象操作 SameType 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同类型。它在被调用时执行以下步骤:

  1. 如果 xundefinedyundefined,返回 true
  2. 如果 xnullynull,返回 true
  3. 如果 x 是布尔值y 是布尔值,返回 true
  4. 如果 x 是数字y 是数字,返回 true
  5. 如果 x 是 BigInty 是 BigInt,返回 true
  6. 如果 x 是符号y 是符号,返回 true
  7. 如果 x 是字符串y 是字符串,返回 true
  8. 如果 x 是对象y 是对象,返回 true
  9. 返回 false

7.2.9 SameValue ( x, y )

抽象操作 SameValue 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同值。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::sameValue(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

此算法与 IsStrictlyEqual 算法不同,它将所有 NaN 值视为等价,并区分 +0𝔽-0𝔽

7.2.10 SameValueZero ( x, y )

抽象操作 SameValueZero 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它确定两个参数是否为相同值(忽略 +0𝔽-0𝔽 之间的区别)。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::sameValueZero(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

SameValueZero 与 SameValue 的区别仅在于它将 +0𝔽-0𝔽 视为等价。

7.2.11 SameValueNonNumber ( x, y )

抽象操作 SameValueNonNumber 接受参数 x(一个ECMAScript 语言值,但不是数字)和 y(一个ECMAScript 语言值,但不是数字)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 断言SameType(x, y) 是 true
  2. 如果 xnullundefined,返回 true
  3. 如果 x 是 BigInt,那么
    1. 返回 BigInt::equal(x, y)。
  4. 如果 x 是字符串,那么
    1. 如果 xy 有相同的长度且在相同位置有相同的代码单元,返回 true;否则,返回 false
  5. 如果 x 是布尔值,那么
    1. 如果 xy 都是 true 或都是 false,返回 true;否则,返回 false
  6. 注意:所有其他ECMAScript 语言值按标识进行比较。
  7. 如果 xy,返回 true;否则,返回 false
注意 1
为了说明目的,即使不必要,此算法中的某些情况也被单独处理。
注意 2
"xy"的具体含义详见5.2.7

7.2.12 IsLessThan ( x, y, LeftFirst )

抽象操作 IsLessThan 接受参数 x(一个ECMAScript 语言值)、y(一个ECMAScript 语言值)和 LeftFirst(一个布尔值)并返回一个包含布尔值或 undefined正常完成,或一个throw 完成。它为比较 x < y 提供语义,返回 truefalseundefined(表示至少一个操作数是 NaN)。LeftFirst 标志用于控制对 xy 执行可能具有可见副作用的操作的顺序。这是必要的,因为 ECMAScript 指定表达式的从左到右求值。如果 LeftFirsttruex 参数对应于出现在 y 参数对应表达式左侧的表达式。如果 LeftFirstfalse,则相反,必须在 x 之前对 y 执行操作。它在被调用时执行以下步骤:

  1. 如果 LeftFirsttrue,那么
    1. px 为 ? ToPrimitive(x, number)。
    2. py 为 ? ToPrimitive(y, number)。
  2. 否则,
    1. 注意:需要颠倒求值顺序以保持从左到右的求值。
    2. py 为 ? ToPrimitive(y, number)。
    3. px 为 ? ToPrimitive(x, number)。
  3. 如果 px 是字符串py 是字符串,那么
    1. lxpx 的长度。
    2. lypy 的长度。
    3. 对于每个整数 i,满足 0 ≤ i < min(lx, ly),按升序执行
      1. cxpx 中索引 i 处代码单元的数值。
      2. cypy 中索引 i 处代码单元的数值。
      3. 如果 cx < cy,返回 true
      4. 如果 cx > cy,返回 false
    4. 如果 lx < ly,返回 true。否则,返回 false
  4. 否则,
    1. 如果 px 是 BigIntpy 是字符串,那么
      1. nyStringToBigInt(py)。
      2. 如果 nyundefined,返回 undefined
      3. 返回 BigInt::lessThan(px, ny)。
    2. 如果 px 是字符串py 是 BigInt,那么
      1. nxStringToBigInt(px)。
      2. 如果 nxundefined,返回 undefined
      3. 返回 BigInt::lessThan(nx, py)。
    3. 注意:因为 pxpy 是原始值,求值顺序不重要。
    4. nx 为 ? ToNumeric(px)。
    5. ny 为 ? ToNumeric(py)。
    6. 如果 SameType(nx, ny) 是 true,那么
      1. 如果 nx 是数字,那么
        1. 返回 Number::lessThan(nx, ny)。
      2. 否则,
        1. 断言nx 是 BigInt
        2. 返回 BigInt::lessThan(nx, ny)。
    7. 断言nx 是 BigIntny 是数字,或 nx 是数字ny 是 BigInt
    8. 如果 nxnyNaN,返回 undefined
    9. 如果 nx-∞𝔽ny+∞𝔽,返回 true
    10. 如果 nx+∞𝔽ny-∞𝔽,返回 false
    11. 如果 (nx) < (ny),返回 true;否则返回 false
注意 1

步骤 3 与处理加法运算符 +13.15.3)的算法中的步骤 1.c 不同,它使用逻辑与操作而不是逻辑或操作。

注意 2

字符串的比较使用 UTF-16 代码单元值序列的简单字典序。没有尝试使用 Unicode 规范中定义的更复杂的、面向语义的字符或字符串相等性和整理顺序定义。因此,根据 Unicode 标准规范相等但不在相同规范化形式中的字符串值可能测试为不相等。还要注意,对于包含代理对的字符串,按代码单元的字典序与按代码点的顺序不同。

7.2.13 IsLooselyEqual ( x, y )

抽象操作 IsLooselyEqual 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它为 == 运算符提供语义。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 true,那么
    1. 返回 IsStrictlyEqual(x, y)。
  2. 如果 xnullyundefined,返回 true
  3. 如果 xundefinedynull,返回 true
  4. 注意:此步骤在B.3.6.2 节中被替换。
  5. 如果 x 是数字y 是字符串,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  6. 如果 x 是字符串y 是数字,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  7. 如果 x 是 BigInty 是字符串,那么
    1. nStringToBigInt(y)。
    2. 如果 nundefined,返回 false
    3. 返回 ! IsLooselyEqual(x, n)。
  8. 如果 x 是字符串y 是 BigInt,返回 ! IsLooselyEqual(y, x)。
  9. 如果 x 是布尔值,返回 ! IsLooselyEqual(! ToNumber(x), y)。
  10. 如果 y 是布尔值,返回 ! IsLooselyEqual(x, ! ToNumber(y))。
  11. 如果 x 是字符串、数字、BigInt 或符号,且 y 是对象,返回 ! IsLooselyEqual(x, ? ToPrimitive(y))。
  12. 如果 x 是对象y 是字符串、数字、BigInt 或符号,返回 ! IsLooselyEqual(? ToPrimitive(x), y)。
  13. 如果 x 是 BigInty 是数字,或如果 x 是数字y 是 BigInt,那么
    1. 如果 x 不是有限的y 不是有限的,返回 false
    2. 如果 (x) = (y),返回 true;否则返回 false
  14. 返回 false

7.2.14 IsStrictlyEqual ( x, y )

抽象操作 IsStrictlyEqual 接受参数 x(一个ECMAScript 语言值)和 y(一个ECMAScript 语言值)并返回一个布尔值。它为 === 运算符提供语义。它在被调用时执行以下步骤:

  1. 如果 SameType(x, y) 是 false,返回 false
  2. 如果 x 是数字,那么
    1. 返回 Number::equal(x, y)。
  3. 返回 SameValueNonNumber(x, y)。
注意

此算法与 SameValue 算法在处理有符号零和 NaN 方面有所不同。

7.3 对象操作

7.3.1 MakeBasicObject ( internalSlotsList )

抽象操作 MakeBasicObject 接受参数 internalSlotsList(一个内部槽名称的列表)并返回一个对象。它是所有算法创建的 ECMAScript 对象的源头,包括普通对象异质对象。它提取了创建所有对象时使用的通用步骤,并集中了对象创建过程。它在被调用时执行以下步骤:

  1. internalSlotsListinternalSlotsList 和 « [[PrivateElements]] » 的列表连接
  2. obj 为一个新创建的对象,为 internalSlotsList 中的每个名称都有一个内部槽。
  3. 注意:如对象内部方法和内部槽中所述,除非另有规定,每个这样的内部槽的初始值都是 undefined
  4. obj.[[PrivateElements]] 为一个新的空列表
  5. obj 的基本内部方法设置为10.1 中指定的默认普通对象定义。
  6. 断言:如果调用者不会覆盖 obj[[GetPrototypeOf]][[SetPrototypeOf]] 基本内部方法,那么 internalSlotsList 包含 [[Prototype]]
  7. 断言:如果调用者不会覆盖 obj 的所有 [[SetPrototypeOf]][[IsExtensible]][[PreventExtensions]] 基本内部方法,那么 internalSlotsList 包含 [[Extensible]]
  8. 如果 internalSlotsList 包含 [[Extensible]],设 obj.[[Extensible]]true
  9. 返回 obj
注意

在本规范中,异质对象是在诸如 ArrayCreateBoundFunctionCreate抽象操作中创建的,首先调用 MakeBasicObject 来获得一个基本的基础对象,然后覆盖该对象的一些或所有内部方法。为了封装异质对象的创建,对象的基本内部方法永远不会在这些操作之外被修改。

7.3.2 Get ( O, P )

抽象操作 Get 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于检索对象的特定属性的值。它在被调用时执行以下步骤:

  1. 返回 ? O.[[Get]](P, O)。

7.3.3 GetV ( V, P )

抽象操作 GetV 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于检索ECMAScript 语言值的特定属性的值。如果该值不是对象,则使用适合该值类型的包装器对象执行属性查找。它在被调用时执行以下步骤:

  1. O 为 ? ToObject(V)。
  2. 返回 ? O.[[Get]](P, V)。

7.3.4 Set ( O, P, V, Throw )

抽象操作 Set 接受参数 O(一个对象)、P(一个属性键)、V(一个ECMAScript 语言值)和 Throw(一个布尔值)并返回一个包含 unused正常完成或一个throw 完成。它用于设置对象的特定属性的值。V 是该属性的新值。它在被调用时执行以下步骤:

  1. success 为 ? O.[[Set]](P, V, O)。
  2. 如果 successfalseThrowtrue,抛出 TypeError 异常。
  3. 返回 unused

7.3.5 CreateDataProperty ( O, P, V )

抽象操作 CreateDataProperty 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它用于创建对象的新自有属性。它在被调用时执行以下步骤:

  1. newDesc 为 PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 返回 ? O.[[DefineOwnProperty]](P, newDesc)。
注意

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性还不存在。如果它存在且不可配置,或者如果 O 不可扩展,[[DefineOwnProperty]] 将返回 false

7.3.6 CreateDataPropertyOrThrow ( O, P, V )

抽象操作 CreateDataPropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它用于创建对象的新自有属性。如果请求的属性更新无法执行,它抛出 TypeError 异常。它在被调用时执行以下步骤:

  1. success 为 ? CreateDataProperty(O, P, V)。
  2. 如果 successfalse,抛出 TypeError 异常。
  3. 返回 unused
注意

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值。通常,该属性还不存在。如果它存在且不可配置,或者如果 O 不可扩展,[[DefineOwnProperty]] 将返回 false,导致此操作抛出 TypeError 异常。

7.3.7 CreateNonEnumerableDataPropertyOrThrow ( O, P, V )

抽象操作 CreateNonEnumerableDataPropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 V(一个ECMAScript 语言值)并返回 unused。它用于创建普通对象的新的不可枚举自有属性。它在被调用时执行以下步骤:

  1. 断言O 是一个普通的、可扩展的、没有不可配置属性的对象。
  2. newDesc 为 PropertyDescriptor { [[Value]]: V, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。
  3. 执行 ! DefinePropertyOrThrow(O, P, newDesc)。
  4. 返回 unused
注意

此抽象操作创建一个属性,其特性设置为与 ECMAScript 语言赋值运算符创建的属性相同的默认值,但它不可枚举。通常,该属性还不存在。如果它存在,DefinePropertyOrThrow 保证正常完成。

7.3.8 DefinePropertyOrThrow ( O, P, desc )

抽象操作 DefinePropertyOrThrow 接受参数 O(一个对象)、P(一个属性键)和 desc(一个属性描述符)并返回一个包含 unused正常完成或一个throw 完成。它用于以一种方式调用对象的 [[DefineOwnProperty]] 内部方法,如果请求的属性更新无法执行,将抛出 TypeError 异常。它在被调用时执行以下步骤:

  1. success 为 ? O.[[DefineOwnProperty]](P, desc)。
  2. 如果 successfalse,抛出 TypeError 异常。
  3. 返回 unused

7.3.9 DeletePropertyOrThrow ( O, P )

抽象操作 DeletePropertyOrThrow 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含 unused正常完成或一个throw 完成。它用于删除对象的特定自有属性。如果属性不可配置,它抛出异常。它在被调用时执行以下步骤:

  1. success 为 ? O.[[Delete]](P)。
  2. 如果 successfalse,抛出 TypeError 异常。
  3. 返回 unused

7.3.10 GetMethod ( V, P )

抽象操作 GetMethod 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)并返回一个包含一个函数对象undefined正常完成,或一个throw 完成。它用于获取ECMAScript 语言值的特定属性的值,当该属性的值预期是一个函数时。它在被调用时执行以下步骤:

  1. func 为 ? GetV(V, P)。
  2. 如果 funcundefinednull,返回 undefined
  3. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  4. 返回 func

7.3.11 HasProperty ( O, P )

抽象操作 HasProperty 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象是否具有指定属性键的属性。该属性可能是自有的或继承的。它在被调用时执行以下步骤:

  1. 返回 ? O.[[HasProperty]](P)。

7.3.12 HasOwnProperty ( O, P )

抽象操作 HasOwnProperty 接受参数 O(一个对象)和 P(一个属性键)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象是否具有指定属性键的自有属性。它在被调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,返回 false
  3. 返回 true

7.3.13 Call ( F, V [ , argumentsList ] )

抽象操作 Call 接受参数 F(一个ECMAScript 语言值)和 V(一个ECMAScript 语言值)以及可选参数 argumentsList(一个ECMAScript 语言值列表)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于调用函数对象[[Call]] 内部方法。F函数对象V 是作为 [[Call]]this 值的ECMAScript 语言值argumentsList 是传递给内部方法相应参数的值。如果 argumentsList 不存在,则使用一个新的空列表作为其值。它在被调用时执行以下步骤:

  1. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  2. 如果 IsCallable(F) 是 false,抛出 TypeError 异常。
  3. 返回 ? F.[[Call]](V, argumentsList)。

7.3.14 Construct ( F [ , argumentsList [ , newTarget ] ] )

抽象操作 Construct 接受参数 F(一个构造器)以及可选参数 argumentsList(一个ECMAScript 语言值列表)和 newTarget(一个构造器)并返回一个包含对象的正常完成或一个throw 完成。它用于调用函数对象[[Construct]] 内部方法。argumentsListnewTarget 是要作为内部方法相应参数传递的值。如果 argumentsList 不存在,则使用一个新的空列表作为其值。如果 newTarget 不存在,则使用 F 作为其值。它在被调用时执行以下步骤:

  1. 如果 newTarget 不存在,设 newTargetF
  2. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  3. 返回 ? F.[[Construct]](argumentsList, newTarget)。
注意

如果 newTarget 不存在,此操作等价于:new F(...argumentsList)

7.3.15 SetIntegrityLevel ( O, level )

抽象操作 SetIntegrityLevel 接受参数 O(一个对象)和 levelsealedfrozen)并返回一个包含布尔值的正常完成或一个throw 完成。它用于固定对象自有属性的集合。它在被调用时执行以下步骤:

  1. status 为 ? O.[[PreventExtensions]]()。
  2. 如果 statusfalse,返回 false
  3. keys 为 ? O.[[OwnPropertyKeys]]()。
  4. 如果 levelsealed,那么
    1. 对于 keys 的每个元素 k,执行
      1. 执行 ? DefinePropertyOrThrow(O, k, PropertyDescriptor { [[Configurable]]: false })。
  5. 否则,
    1. 断言levelfrozen
    2. 对于 keys 的每个元素 k,执行
      1. currentDesc 为 ? O.[[GetOwnProperty]](k)。
      2. 如果 currentDesc 不是 undefined,那么
        1. 如果 IsAccessorDescriptor(currentDesc) 是 true,那么
          1. desc 为 PropertyDescriptor { [[Configurable]]: false }。
        2. 否则,
          1. desc 为 PropertyDescriptor { [[Configurable]]: false, [[Writable]]: false }。
        3. 执行 ? DefinePropertyOrThrow(O, k, desc)。
  6. 返回 true

7.3.16 TestIntegrityLevel ( O, level )

抽象操作 TestIntegrityLevel 接受参数 O(一个对象)和 levelsealedfrozen)并返回一个包含布尔值的正常完成或一个throw 完成。它用于确定对象自有属性的集合是否被固定。它在被调用时执行以下步骤:

  1. extensible 为 ? IsExtensible(O)。
  2. 如果 extensibletrue,返回 false
  3. 注意:如果对象是可扩展的,则不检查其任何属性。
  4. keys 为 ? O.[[OwnPropertyKeys]]()。
  5. 对于 keys 的每个元素 k,执行
    1. currentDesc 为 ? O.[[GetOwnProperty]](k)。
    2. 如果 currentDesc 不是 undefined,那么
      1. 如果 currentDesc.[[Configurable]]true,返回 false
      2. 如果 levelfrozenIsDataDescriptor(currentDesc) 是 true,那么
        1. 如果 currentDesc.[[Writable]]true,返回 false
  6. 返回 true

7.3.17 CreateArrayFromList ( elements )

抽象操作 CreateArrayFromList 接受参数 elements(一个ECMAScript 语言值列表)并返回一个数组。它用于创建一个由 elements 提供元素的数组。它在被调用时执行以下步骤:

  1. array 为 ! ArrayCreate(0)。
  2. n 为 0。
  3. 对于 elements 的每个元素 e,执行
    1. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(n)), e)。
    2. nn + 1。
  4. 返回 array

7.3.18 LengthOfArrayLike ( obj )

抽象操作 LengthOfArrayLike 接受参数 obj(一个对象)并返回一个包含非负整数正常完成或一个throw 完成。它返回类数组对象的 "length" 属性的值。它在被调用时执行以下步骤:

  1. 返回 (? ToLength(? Get(obj, "length")))。

类数组对象是此操作返回正常完成的任何对象。

注意 1
通常,类数组对象还会有一些带有整数索引名称的属性。但是,这不是此定义的要求。
注意 2
数组和字符串对象是类数组对象的例子。

7.3.19 CreateListFromArrayLike ( obj [ , validElementTypes ] )

抽象操作 CreateListFromArrayLike 接受参数 obj(一个ECMAScript 语言值)和可选参数 validElementTypesallproperty-key)并返回一个包含ECMAScript 语言值列表正常完成或一个throw 完成。它用于创建一个列表值,其元素由 obj 的索引属性提供。validElementTypes 指示允许作为元素的值的类型。它在被调用时执行以下步骤:

  1. 如果 validElementTypes 不存在,设 validElementTypesall
  2. 如果 obj 不是对象,抛出 TypeError 异常。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. list 为一个新的空列表
  5. index 为 0。
  6. 重复,当 index < len 时,
    1. indexName 为 ! ToString(𝔽(index))。
    2. next 为 ? Get(obj, indexName)。
    3. 如果 validElementTypesproperty-keynext 不是属性键,抛出 TypeError 异常。
    4. next 追加到 list
    5. indexindex + 1。
  7. 返回 list

7.3.20 Invoke ( V, P [ , argumentsList ] )

抽象操作 Invoke 接受参数 V(一个ECMAScript 语言值)和 P(一个属性键)以及可选参数 argumentsList(一个ECMAScript 语言值列表)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它用于调用ECMAScript 语言值的方法属性。V 既作为属性的查找点,也作为调用的 this 值。argumentsList 是传递给方法的参数值列表。如果 argumentsList 不存在,则使用一个新的空列表作为其值。它在被调用时执行以下步骤:

  1. 如果 argumentsList 不存在,设 argumentsList 为一个新的空列表
  2. func 为 ? GetV(V, P)。
  3. 返回 ? Call(func, V, argumentsList)。

7.3.21 OrdinaryHasInstance ( C, O )

抽象操作 OrdinaryHasInstance 接受参数 C(一个ECMAScript 语言值)和 O(一个ECMAScript 语言值)并返回一个包含布尔值的正常完成或一个throw 完成。它实现了确定 O 是否继承自 C 提供的实例对象继承路径的默认算法。它在被调用时执行以下步骤:

  1. 如果 IsCallable(C) 是 false,返回 false
  2. 如果 C[[BoundTargetFunction]] 内部槽,那么
    1. BCC.[[BoundTargetFunction]]
    2. 返回 ? InstanceofOperator(O, BC)。
  3. 如果 O 不是对象,返回 false
  4. P 为 ? Get(C, "prototype")。
  5. 如果 P 不是对象,抛出 TypeError 异常。
  6. 重复,
    1. O 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 Onull,返回 false
    3. 如果 SameValue(P, O) 是 true,返回 true

7.3.22 SpeciesConstructor ( O, defaultConstructor )

抽象操作 SpeciesConstructor 接受参数 O(一个对象)和 defaultConstructor(一个构造器)并返回一个包含一个构造器正常完成或一个throw 完成。它用于检索应该用于创建从 O 派生的新对象的构造器defaultConstructor 是当从 O 开始无法找到构造器 %Symbol.species% 属性时要使用的构造器。它在被调用时执行以下步骤:

  1. C 为 ? Get(O, "constructor")。
  2. 如果 Cundefined,返回 defaultConstructor
  3. 如果 C 不是对象,抛出 TypeError 异常。
  4. S 为 ? Get(C, %Symbol.species%)。
  5. 如果 Sundefinednull,返回 defaultConstructor
  6. 如果 IsConstructor(S) 是 true,返回 S
  7. 抛出 TypeError 异常。

7.3.23 EnumerableOwnProperties ( O, kind )

抽象操作 EnumerableOwnProperties 接受参数 O(一个对象)和 kindkeyvaluekey+value)并返回一个包含ECMAScript 语言值列表正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. ownKeys 为 ? O.[[OwnPropertyKeys]]()。
  2. results 为一个新的空列表
  3. 对于 ownKeys 的每个元素 key,执行
    1. 如果 key 是字符串,那么
      1. desc 为 ? O.[[GetOwnProperty]](key)。
      2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
        1. 如果 kindkey,那么
          1. key 追加到 results
        2. 否则,
          1. value 为 ? Get(O, key)。
          2. 如果 kindvalue,那么
            1. value 追加到 results
          3. 否则,
            1. 断言kindkey+value
            2. entryCreateArrayFromListkey, value »)。
            3. entry 追加到 results
  4. 返回 results

7.3.24 GetFunctionRealm ( obj )

抽象操作 GetFunctionRealm 接受参数 obj(一个函数对象)并返回一个包含一个Realm Record正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 obj[[Realm]] 内部槽,那么
    1. 返回 obj.[[Realm]]
  2. 如果 obj绑定函数异质对象,那么
    1. boundTargetFunctionobj.[[BoundTargetFunction]]
    2. 返回 ? GetFunctionRealm(boundTargetFunction)。
  3. 如果 obj代理异质对象,那么
    1. 执行 ? ValidateNonRevokedProxy(obj)。
    2. proxyTargetobj.[[ProxyTarget]]
    3. 断言proxyTarget 是一个函数对象
    4. 返回 ? GetFunctionRealm(proxyTarget)。
  4. 返回当前 Realm Record
注意

只有当 obj 是一个没有 [[Realm]] 内部槽的非标准函数异质对象时,才会执行步骤4

7.3.25 CopyDataProperties ( target, source, excludedItems )

抽象操作 CopyDataProperties 接受参数 target(一个对象)、source(一个ECMAScript 语言值)和 excludedItems(一个属性键列表)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 sourceundefinednull,返回 unused
  2. from 为 ! ToObject(source)。
  3. keys 为 ? from.[[OwnPropertyKeys]]()。
  4. 对于 keys 的每个元素 nextKey,执行
    1. excludedfalse
    2. 对于 excludedItems 的每个元素 e,执行
      1. 如果 SameValue(e, nextKey) 是 true,那么
        1. excludedtrue
    3. 如果 excludedfalse,那么
      1. desc 为 ? from.[[GetOwnProperty]](nextKey)。
      2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
        1. propValue 为 ? Get(from, nextKey)。
        2. 执行 ! CreateDataPropertyOrThrow(target, nextKey, propValue)。
  5. 返回 unused
注意

这里传入的目标总是一个新创建的对象,在抛出错误的情况下不能直接访问。

7.3.26 PrivateElementFind ( O, P )

抽象操作 PrivateElementFind 接受参数 O(一个对象)和 P(一个私有名称)并返回一个PrivateElementempty。它在被调用时执行以下步骤:

  1. 如果 O.[[PrivateElements]] 包含一个PrivateElement pe,其中 pe.[[Key]]P,那么
    1. 返回 pe
  2. 返回 empty

7.3.27 PrivateFieldAdd ( O, P, value )

抽象操作 PrivateFieldAdd 接受参数 O(一个对象)、P(一个私有名称)和 value(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果宿主是 Web 浏览器,那么
    1. 执行 ? HostEnsureCanAddPrivateElement(O)。
  2. entryPrivateElementFind(O, P)。
  3. 如果 entry 不是 empty,抛出 TypeError 异常。
  4. PrivateElement { [[Key]]: P, [[Kind]]: field, [[Value]]: value } 追加到 O.[[PrivateElements]]
  5. 返回 unused

7.3.28 PrivateMethodOrAccessorAdd ( O, method )

抽象操作 PrivateMethodOrAccessorAdd 接受参数 O(一个对象)和 method(一个PrivateElement)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 断言method.[[Kind]]methodaccessor
  2. 如果宿主是 Web 浏览器,那么
    1. 执行 ? HostEnsureCanAddPrivateElement(O)。
  3. entryPrivateElementFind(O, method.[[Key]])。
  4. 如果 entry 不是 empty,抛出 TypeError 异常。
  5. method 追加到 O.[[PrivateElements]]
  6. 返回 unused
注意

私有方法和访问器的值在实例之间共享。此操作不会创建方法或访问器的新副本。

7.3.29 HostEnsureCanAddPrivateElement ( O )

宿主定义的抽象操作 HostEnsureCanAddPrivateElement 接受参数 O(一个对象)并返回一个包含 unused正常完成或一个throw 完成。它允许宿主环境阻止向特定的宿主定义的异质对象添加私有元素。

HostEnsureCanAddPrivateElement 的实现必须符合以下要求:

HostEnsureCanAddPrivateElement 的默认实现是返回 NormalCompletion(unused)。

此抽象操作仅由作为 Web 浏览器的 ECMAScript 宿主调用。

7.3.30 PrivateGet ( O, P )

抽象操作 PrivateGet 接受参数 O(一个对象)和 P(一个私有名称)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. entryPrivateElementFind(O, P)。
  2. 如果 entryempty,抛出 TypeError 异常。
  3. 如果 entry.[[Kind]]fieldmethod,那么
    1. 返回 entry.[[Value]]
  4. 断言entry.[[Kind]]accessor
  5. 如果 entry.[[Get]]undefined,抛出 TypeError 异常。
  6. getterentry.[[Get]]
  7. 返回 ? Call(getter, O)。

7.3.31 PrivateSet ( O, P, value )

抽象操作 PrivateSet 接受参数 O(一个对象)、P(一个私有名称)和 value(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. entryPrivateElementFind(O, P)。
  2. 如果 entryempty,抛出 TypeError 异常。
  3. 如果 entry.[[Kind]]field,那么
    1. entry.[[Value]]value
  4. 否则如果 entry.[[Kind]]method,那么
    1. 抛出 TypeError 异常。
  5. 否则,
    1. 断言entry.[[Kind]]accessor
    2. 如果 entry.[[Set]]undefined,抛出 TypeError 异常。
    3. setterentry.[[Set]]
    4. 执行 ? Call(setter, O, « value »)。
  6. 返回 unused

7.3.32 DefineField ( receiver, fieldRecord )

抽象操作 DefineField 接受参数 receiver(一个对象)和 fieldRecord(一个ClassFieldDefinition Record)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. fieldNamefieldRecord.[[Name]]
  2. initializerfieldRecord.[[Initializer]]
  3. 如果 initializer 不是 empty,那么
    1. initValue 为 ? Call(initializer, receiver)。
  4. 否则,
    1. initValueundefined
  5. 如果 fieldName私有名称,那么
    1. 执行 ? PrivateFieldAdd(receiver, fieldName, initValue)。
  6. 否则,
    1. 断言fieldName 是一个属性键
    2. 执行 ? CreateDataPropertyOrThrow(receiver, fieldName, initValue)。
  7. 返回 unused

7.3.33 InitializeInstanceElements ( O, constructor )

抽象操作 InitializeInstanceElements 接受参数 O(一个对象)和 constructor(一个 ECMAScript 函数对象)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. methodsconstructor.[[PrivateMethods]] 的值。
  2. 对于 methods 的每个PrivateElement method,执行
    1. 执行 ? PrivateMethodOrAccessorAdd(O, method)。
  3. fieldsconstructor.[[Fields]] 的值。
  4. 对于 fields 的每个元素 fieldRecord,执行
    1. 执行 ? DefineField(O, fieldRecord)。
  5. 返回 unused

7.3.34 AddValueToKeyedGroup ( groups, key, value )

抽象操作 AddValueToKeyedGroup 接受参数 groups(一个记录列表,具有字段 [[Key]](一个ECMAScript 语言值)和 [[Elements]](一个ECMAScript 语言值列表))、key(一个ECMAScript 语言值)和 value(一个ECMAScript 语言值)并返回 unused。它在被调用时执行以下步骤:

  1. 对于 groups 的每个记录 { [[Key]], [[Elements]] } g,执行
    1. 如果 SameValue(g.[[Key]], key) 是 true,那么
      1. 断言groups 中恰好有一个元素满足此条件。
      2. value 追加到 g.[[Elements]]
      3. 返回 unused
  2. group记录 { [[Key]]: key, [[Elements]]: « value » }。
  3. group 追加到 groups
  4. 返回 unused

7.3.35 GroupBy ( items, callback, keyCoercion )

抽象操作 GroupBy 接受参数 items(一个ECMAScript 语言值)、callback(一个ECMAScript 语言值)和 keyCoercionpropertycollection)并返回一个包含记录列表正常完成(具有字段 [[Key]](一个ECMAScript 语言值)和 [[Elements]](一个ECMAScript 语言值列表))或一个throw 完成。它在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(items)。
  2. 如果 IsCallable(callback) 是 false,抛出 TypeError 异常。
  3. groups 为一个新的空列表
  4. iteratorRecord 为 ? GetIterator(items, sync)。
  5. k 为 0。
  6. 重复,
    1. 如果 k ≥ 253 - 1,那么
      1. errorThrowCompletion(新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    2. next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,那么
      1. 返回 groups
    4. valuenext
    5. keyCompletion(Call(callback, undefined, « value, 𝔽(k) »))。
    6. IfAbruptCloseIterator(key, iteratorRecord)。
    7. 如果 keyCoercionproperty,那么
      1. keyCompletion(ToPropertyKey(key))。
      2. IfAbruptCloseIterator(key, iteratorRecord)。
    8. 否则,
      1. 断言keyCoercioncollection
      2. keyCanonicalizeKeyedCollectionKey(key)。
    9. 执行 AddValueToKeyedGroup(groups, key, value)。
    10. kk + 1。

7.3.36 SetterThatIgnoresPrototypeProperties ( thisValue, home, p, v )

抽象操作 SetterThatIgnoresPrototypeProperties 接受参数 thisValue(一个ECMAScript 语言值)、home(一个对象)、p(一个属性键)和 v(一个ECMAScript 语言值)并返回一个包含 unused正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 thisValue 不是对象,那么
    1. 抛出 TypeError 异常。
  2. 如果 SameValue(thisValue, home) 是 true,那么
    1. 注意:这里抛出异常模拟了在严格模式代码中对 home 对象上不可写数据属性的赋值。
    2. 抛出 TypeError 异常。
  3. desc 为 ? thisValue.[[GetOwnProperty]](p)。
  4. 如果 descundefined,那么
    1. 执行 ? CreateDataPropertyOrThrow(thisValue, p, v)。
  5. 否则,
    1. 执行 ? Set(thisValue, p, v, true)。
  6. 返回 unused

7.4 迭代器对象上的操作

参见通用迭代接口(27.1)。

7.4.1 迭代器记录

迭代器记录是一个记录值,用于封装一个迭代器异步迭代器以及其 next 方法。

迭代器记录具有表 15中列出的字段。

表 15:迭代器记录字段
字段名称 含义
[[Iterator]] 一个对象 符合迭代器接口异步迭代器接口的对象。
[[NextMethod]] 一个ECMAScript 语言值 [[Iterator]] 对象的 next 方法。
[[Done]] 一个布尔值 迭代器是否已完成或已关闭。

7.4.2 GetIteratorDirect ( obj )

抽象操作 GetIteratorDirect 接受参数 obj(一个对象)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. nextMethod 为 ? Get(obj, "next")。
  2. iteratorRecord迭代器记录 { [[Iterator]]: obj, [[NextMethod]]: nextMethod, [[Done]]: false }。
  3. 返回 iteratorRecord

7.4.3 GetIteratorFromMethod ( obj, method )

抽象操作 GetIteratorFromMethod 接受参数 obj(一个ECMAScript 语言值)和 method(一个函数对象)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. iterator 为 ? Call(method, obj)。
  2. 如果 iterator 不是对象,抛出 TypeError 异常。
  3. 返回 ? GetIteratorDirect(iterator)。

7.4.4 GetIterator ( obj, kind )

抽象操作 GetIterator 接受参数 obj(一个ECMAScript 语言值)和 kindsyncasync)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 kindasync,那么
    1. method 为 ? GetMethod(obj, %Symbol.asyncIterator%)。
    2. 如果 methodundefined,那么
      1. syncMethod 为 ? GetMethod(obj, %Symbol.iterator%)。
      2. 如果 syncMethodundefined,抛出 TypeError 异常。
      3. syncIteratorRecord 为 ? GetIteratorFromMethod(obj, syncMethod)。
      4. 返回 CreateAsyncFromSyncIterator(syncIteratorRecord)。
  2. 否则,
    1. method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 methodundefined,抛出 TypeError 异常。
  4. 返回 ? GetIteratorFromMethod(obj, method)。

7.4.5 GetIteratorFlattenable ( obj, primitiveHandling )

抽象操作 GetIteratorFlattenable 接受参数 obj(一个ECMAScript 语言值)和 primitiveHandlingiterate-string-primitivesreject-primitives)并返回一个包含一个迭代器记录正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 obj 不是对象,那么
    1. 如果 primitiveHandlingreject-primitives,抛出 TypeError 异常。
    2. 断言primitiveHandlingiterate-string-primitives
    3. 如果 obj 不是字符串,抛出 TypeError 异常。
  2. method 为 ? GetMethod(obj, %Symbol.iterator%)。
  3. 如果 methodundefined,那么
    1. iteratorobj
  4. 否则,
    1. iterator 为 ? Call(method, obj)。
  5. 如果 iterator 不是对象,抛出 TypeError 异常。
  6. 返回 ? GetIteratorDirect(iterator)。

7.4.6 IteratorNext ( iteratorRecord [ , value ] )

抽象操作 IteratorNext 接受参数 iteratorRecord(一个迭代器记录)和可选参数 value(一个ECMAScript 语言值)并返回一个包含一个对象的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 如果 value 不存在,那么
    1. resultCompletion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]))。
  2. 否则,
    1. resultCompletion(Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « value »))。
  3. 如果 resultthrow 完成,那么
    1. iteratorRecord.[[Done]]true
    2. 返回 ? result
  4. result 为 ! result
  5. 如果 result 不是对象,那么
    1. iteratorRecord.[[Done]]true
    2. 抛出 TypeError 异常。
  6. 返回 result

7.4.7 IteratorComplete ( iteratorResult )

抽象操作 IteratorComplete 接受参数 iteratorResult(一个对象)并返回一个包含一个布尔值的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 返回 ToBoolean(? Get(iteratorResult, "done"))。

7.4.8 IteratorValue ( iteratorResult )

抽象操作 IteratorValue 接受参数 iteratorResult(一个对象)并返回一个包含一个ECMAScript 语言值正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. 返回 ? Get(iteratorResult, "value")。

7.4.9 IteratorStep ( iteratorRecord )

抽象操作 IteratorStep 接受参数 iteratorRecord(一个迭代器记录)并返回一个包含一个对象或 done正常完成,或一个throw 完成。它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或IteratorResult 对象(如果下一个值可用)。它在被调用时执行以下步骤:

  1. result 为 ? IteratorNext(iteratorRecord)。
  2. doneCompletion(IteratorComplete(result))。
  3. 如果 donethrow 完成,那么
    1. iteratorRecord.[[Done]]true
    2. 返回 ? done
  4. done 为 ! done
  5. 如果 donetrue,那么
    1. iteratorRecord.[[Done]]true
    2. 返回 done
  6. 返回 result

7.4.10 IteratorStepValue ( iteratorRecord )

抽象操作 IteratorStepValue 接受参数 iteratorRecord(一个迭代器记录)并返回一个包含一个ECMAScript 语言值done正常完成,或一个throw 完成。它通过调用 iteratorRecord.[[NextMethod]]iteratorRecord.[[Iterator]] 请求下一个值,并返回 done(表示迭代器已到达末尾)或来自IteratorResult 对象的值(如果下一个值可用)。它在被调用时执行以下步骤:

  1. result 为 ? IteratorStep(iteratorRecord)。
  2. 如果 resultdone,那么
    1. 返回 done
  3. valueCompletion(IteratorValue(result))。
  4. 如果 valuethrow 完成,那么
    1. iteratorRecord.[[Done]]true
  5. 返回 ? value

7.4.11 IteratorClose ( iteratorRecord, completion )

抽象操作 IteratorClose 接受参数 iteratorRecord(一个迭代器记录)和 completion(一个完成记录)并返回一个完成记录。它用于通知迭代器应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:

  1. 断言iteratorRecord.[[Iterator]] 是一个对象
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return"))。
  4. 如果 innerResult正常完成,那么
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,返回 ? completion
    3. innerResultCompletion(Call(return, iterator))。
  5. 如果 completionthrow 完成,返回 ? completion
  6. 如果 innerResultthrow 完成,返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是对象,抛出 TypeError 异常。
  8. 返回 ? completion

7.4.12 IfAbruptCloseIterator ( value, iteratorRecord )

IfAbruptCloseIterator 是使用迭代器记录的算法步骤序列的简写。形式为以下的算法步骤:

  1. IfAbruptCloseIterator(value, iteratorRecord)。

与以下含义相同:

  1. 断言value 是一个完成记录
  2. 如果 value异常完成,返回 ? IteratorClose(iteratorRecord, value)。
  3. 否则,设 value 为 ! value

7.4.13 AsyncIteratorClose ( iteratorRecord, completion )

抽象操作 AsyncIteratorClose 接受参数 iteratorRecord(一个迭代器记录)和 completion(一个完成记录)并返回一个完成记录。它用于通知异步迭代器应该执行它在到达完成状态时通常要执行的任何操作。它在被调用时执行以下步骤:

  1. 断言iteratorRecord.[[Iterator]] 是一个对象
  2. iteratoriteratorRecord.[[Iterator]]
  3. innerResultCompletion(GetMethod(iterator, "return"))。
  4. 如果 innerResult正常完成,那么
    1. returninnerResult.[[Value]]
    2. 如果 returnundefined,返回 ? completion
    3. innerResultCompletion(Call(return, iterator))。
    4. 如果 innerResult正常完成,设 innerResultCompletion(Await(innerResult.[[Value]]))。
  5. 如果 completionthrow 完成,返回 ? completion
  6. 如果 innerResultthrow 完成,返回 ? innerResult
  7. 如果 innerResult.[[Value]] 不是对象,抛出 TypeError 异常。
  8. 返回 ? completion

7.4.14 CreateIteratorResultObject ( value, done )

抽象操作 CreateIteratorResultObject 接受参数 value(一个ECMAScript 语言值)和 done(一个布尔值)并返回一个符合IteratorResult 接口的对象。它创建一个符合IteratorResult 接口的对象。它在被调用时执行以下步骤:

  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ! CreateDataPropertyOrThrow(obj, "value", value)。
  3. 执行 ! CreateDataPropertyOrThrow(obj, "done", done)。
  4. 返回 obj

7.4.15 CreateListIteratorRecord ( list )

抽象操作 CreateListIteratorRecord 接受参数 list(一个包含ECMAScript 语言值列表)并返回一个迭代器记录。它创建一个迭代器记录,其 [[NextMethod]] 返回 list 的连续元素。它在被调用时执行以下步骤:

  1. closure 为一个新的抽象闭包,它没有参数,捕获 list,并在被调用时执行以下步骤:
    1. 对于 list 的每个元素 E,执行
      1. 执行 ? GeneratorYield(CreateIteratorResultObject(E, false))。
    2. 返回 NormalCompletion(undefined)。
  2. iteratorCreateIteratorFromClosure(closure, empty, %Iterator.prototype%)。
  3. 返回迭代器记录 { [[Iterator]]: iterator, [[NextMethod]]: %GeneratorPrototype.next%, [[Done]]: false }。
注意

列表迭代器对象永远不会直接暴露给 ECMAScript 代码。

7.4.16 IteratorToList ( iteratorRecord )

抽象操作 IteratorToList 接受参数 iteratorRecord(一个迭代器记录)并返回一个包含一个列表(包含ECMAScript 语言值)的正常完成或一个throw 完成。它在被调用时执行以下步骤:

  1. values 为一个新的空列表
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,那么
      1. 返回 values
    3. next 追加到 values

8 语法定向操作

除了本节中定义的操作外,专用的语法定向操作在本规范中各处都有定义。

8.1 运行时语义:Evaluation

语法定向操作 Evaluation 不接受参数并返回一个完成记录

注意
此操作的定义分布在本规范的"ECMAScript 语言"章节中。每个定义都出现在相关产生式的定义出现之后。

8.2 作用域分析

8.2.1 静态语义:BoundNames

语法定向操作 BoundNames 不接受参数并返回一个字符串的列表

注意

"*default*" 在本规范中用作模块的默认导出在没有其他名称时的合成名称。模块的 [[Environment]] 中会创建一个具有该名称的条目并保存相应的值,通过为模块调用 ResolveExport ( exportName [ , resolveSet ] ) 来解析名为 "default" 的导出将返回一个 ResolvedBinding 记录,其 [[BindingName]]"*default*",然后在模块的 [[Environment]] 中解析为上述值。这样做只是为了便于规范,使匿名默认导出可以像任何其他导出一样解析。这个 "*default*" 字符串永远不会暴露给 ECMAScript 代码或模块链接算法。

它在以下产生式上分段定义:

BindingIdentifier : Identifier
  1. 返回一个列表,其唯一元素是 IdentifierStringValue
BindingIdentifier : yield
  1. 返回 « "yield" »。
BindingIdentifier : await
  1. 返回 « "await" »。
LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 BindingListBoundNames
BindingList : BindingList , LexicalBinding
  1. names1BindingListBoundNames
  2. names2LexicalBindingBoundNames
  3. 返回 names1names2列表连接
LexicalBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
LexicalBinding : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. names1VariableDeclarationListBoundNames
  2. names2VariableDeclarationBoundNames
  3. 返回 names1names2列表连接
VariableDeclaration : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
VariableDeclaration : BindingPattern Initializer
  1. 返回 BindingPatternBoundNames
ObjectBindingPattern : { }
  1. 返回一个新的空列表
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. names1BindingPropertyListBoundNames
  2. names2BindingRestPropertyBoundNames
  3. 返回 names1names2列表连接
ArrayBindingPattern : [ Elisionopt ]
  1. 返回一个新的空列表
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListBoundNames
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. names1BindingElementListBoundNames
  2. names2BindingRestElementBoundNames
  3. 返回 names1names2列表连接
BindingPropertyList : BindingPropertyList , BindingProperty
  1. names1BindingPropertyListBoundNames
  2. names2BindingPropertyBoundNames
  3. 返回 names1names2列表连接
BindingElementList : BindingElementList , BindingElisionElement
  1. names1BindingElementListBoundNames
  2. names2BindingElisionElementBoundNames
  3. 返回 names1names2列表连接
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementBoundNames
BindingProperty : PropertyName : BindingElement
  1. 返回 BindingElementBoundNames
SingleNameBinding : BindingIdentifier Initializeropt
  1. 返回 BindingIdentifierBoundNames
BindingElement : BindingPattern Initializeropt
  1. 返回 BindingPatternBoundNames
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingBoundNames
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 BindingIdentifierBoundNames
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 « "*default*" »。
FormalParameters : [empty]
  1. 返回一个新的空列表
FormalParameters : FormalParameterList , FunctionRestParameter
  1. names1FormalParameterListBoundNames
  2. names2FunctionRestParameterBoundNames
  3. 返回 names1names2列表连接
FormalParameterList : FormalParameterList , FormalParameter
  1. names1FormalParameterListBoundNames
  2. names2FormalParameterBoundNames
  3. 返回 names1names2列表连接
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsBoundNames
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 返回 BindingIdentifierBoundNames
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 « "*default*" »。
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 BindingIdentifierBoundNames
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 « "*default*" »。
ClassDeclaration : class BindingIdentifier ClassTail
  1. 返回 BindingIdentifierBoundNames
ClassDeclaration : class ClassTail
  1. 返回 « "*default*" »。
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 BindingIdentifierBoundNames
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 « "*default*" »。
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. head 为被 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  2. 返回 headBoundNames
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. 返回 ImportClauseBoundNames
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空列表
ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. names1ImportedDefaultBindingBoundNames
  2. names2NameSpaceImportBoundNames
  3. 返回 names1names2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. names1ImportedDefaultBindingBoundNames
  2. names2NamedImportsBoundNames
  3. 返回 names1names2列表连接
NamedImports : { }
  1. 返回一个新的空列表
ImportsList : ImportsList , ImportSpecifier
  1. names1ImportsListBoundNames
  2. names2ImportSpecifierBoundNames
  3. 返回 names1names2列表连接
ImportSpecifier : ModuleExportName as ImportedBinding
  1. 返回 ImportedBindingBoundNames
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回一个新的空列表
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration
  1. declarationNamesHoistableDeclarationBoundNames
  2. 如果 declarationNames 不包含元素 "*default*",则将 "*default*" 追加到 declarationNames
  3. 返回 declarationNames
ExportDeclaration : export default ClassDeclaration
  1. declarationNamesClassDeclarationBoundNames
  2. 如果 declarationNames 不包含元素 "*default*",则将 "*default*" 追加到 declarationNames
  3. 返回 declarationNames
ExportDeclaration : export default AssignmentExpression ;
  1. 返回 « "*default*" »。

8.2.2 静态语义:DeclarationPart

语法定向操作 DeclarationPart 不接受参数并返回一个解析节点。它在以下产生式上分段定义:

HoistableDeclaration : FunctionDeclaration
  1. 返回 FunctionDeclaration
HoistableDeclaration : GeneratorDeclaration
  1. 返回 GeneratorDeclaration
HoistableDeclaration : AsyncFunctionDeclaration
  1. 返回 AsyncFunctionDeclaration
HoistableDeclaration : AsyncGeneratorDeclaration
  1. 返回 AsyncGeneratorDeclaration
Declaration : ClassDeclaration
  1. 返回 ClassDeclaration
Declaration : LexicalDeclaration
  1. 返回 LexicalDeclaration

8.2.3 静态语义:IsConstantDeclaration

语法定向操作 IsConstantDeclaration 不接受参数并返回一个布尔值。它在以下产生式上分段定义:

LexicalDeclaration : LetOrConst BindingList ;
  1. 返回 LetOrConstIsConstantDeclaration
LetOrConst : let
  1. 返回 false
LetOrConst : const
  1. 返回 true
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false
ClassDeclaration : class BindingIdentifier ClassTail class ClassTail
  1. 返回 false
ExportDeclaration : export ExportFromClause FromClause ; export NamedExports ; export default AssignmentExpression ;
  1. 返回 false
注意

没有必要将 export default AssignmentExpression 视为常量声明,因为没有语法允许对用于引用模块默认对象的内部绑定名称进行赋值。

8.2.4 静态语义:词法声明的名称 (LexicallyDeclaredNames)

语法导向操作 LexicallyDeclaredNames 不接受参数,并返回一个字符串列表。它根据以下产生式分段定义:

Block : { }
  1. 返回一个新的空列表
StatementList : StatementList StatementListItem
  1. names1StatementListLexicallyDeclaredNames
  2. names2StatementListItemLexicallyDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 LabelledStatementLexicallyDeclaredNames
  2. 返回一个新的空列表
StatementListItem : Declaration
  1. 返回 DeclarationBoundNames
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 names1 为第一个 CaseClausesLexicallyDeclaredNames
  2. 否则,令 names1 为一个新的空列表
  3. names2DefaultClauseLexicallyDeclaredNames
  4. 如果第二个 CaseClauses 存在,令 names3 为第二个 CaseClausesLexicallyDeclaredNames
  5. 否则,令 names3 为一个新的空列表
  6. 返回 names1names2names3列表连接
CaseClauses : CaseClauses CaseClause
  1. names1CaseClausesLexicallyDeclaredNames
  2. names2CaseClauseLexicallyDeclaredNames
  3. 返回 names1names2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyDeclaredNames
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyDeclaredNames
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemLexicallyDeclaredNames
LabelledItem : Statement
  1. 返回一个新的空列表
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclarationBoundNames
FunctionStatementList : [空]
  1. 返回一个新的空列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
ConciseBody : ExpressionBody
  1. 返回一个新的空列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空列表
Script : [空]
  1. 返回一个新的空列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelLexicallyDeclaredNames
注 1

Script 的顶层,函数声明被视为类似 var 声明,而不是类似词法声明。

注 2

Module 的 LexicallyDeclaredNames 包含其所有导入绑定的名称。

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListLexicallyDeclaredNames
  2. names2ModuleItemLexicallyDeclaredNames
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration
  1. 返回 ImportDeclarationBoundNames
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回一个新的 空列表
  2. 返回 ExportDeclarationBoundNames
ModuleItem : StatementListItem
  1. 返回 StatementListItemLexicallyDeclaredNames
注 3

Module 的顶层,函数声明被视为类似词法声明,而不是类似 var 声明。

8.2.5 静态语义:词法作用域声明 (LexicallyScopedDeclarations)

语法导向操作 LexicallyScopedDeclarations 不接受参数,并返回一个解析节点列表。它根据以下产生式分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListLexicallyScopedDeclarations
  2. declarations2StatementListItemLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,则返回 LabelledStatementLexicallyScopedDeclarations
  2. 返回一个新的空列表
StatementListItem : Declaration
  1. 返回一个列表,其唯一元素是 DeclarationDeclarationPart
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 declarations1 为第一个 CaseClausesLexicallyScopedDeclarations
  2. 否则,令 declarations1 为一个新的空列表
  3. declarations2DefaultClauseLexicallyScopedDeclarations
  4. 如果第二个 CaseClauses 存在,令 declarations3 为第二个 CaseClausesLexicallyScopedDeclarations
  5. 否则,令 declarations3 为一个新的空列表
  6. 返回 declarations1declarations2declarations3列表连接
CaseClauses : CaseClauses CaseClause
  1. declarations1CaseClausesLexicallyScopedDeclarations
  2. declarations2CaseClauseLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListLexicallyScopedDeclarations
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemLexicallyScopedDeclarations
LabelledItem : Statement
  1. 返回一个新的空列表
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。
FunctionStatementList : [空]
  1. 返回一个新的空列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空列表
Script : [空]
  1. 返回一个新的空列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelLexicallyScopedDeclarations
Module : [空]
  1. 返回一个新的空列表
ModuleItemList : ModuleItemList ModuleItem
  1. declarations1ModuleItemListLexicallyScopedDeclarations
  2. declarations2ModuleItemLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement
  1. 返回一个新的空列表
ExportDeclaration : export Declaration
  1. 返回一个列表,其唯一元素是 DeclarationDeclarationPart
ExportDeclaration : export default HoistableDeclaration
  1. 返回一个列表,其唯一元素是 HoistableDeclarationDeclarationPart
ExportDeclaration : export default ClassDeclaration
  1. 返回一个列表,其唯一元素是 ClassDeclaration
ExportDeclaration : export default AssignmentExpression ;
  1. 返回一个列表,其唯一元素是这个 ExportDeclaration

8.2.6 静态语义:VarDeclaredNames

语法导向操作 VarDeclaredNames 不接受参数,并返回一个字符串列表。它根据以下产生式分段定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空列表
Block : { }
  1. 返回一个新的空列表
StatementList : StatementList StatementListItem
  1. names1StatementListVarDeclaredNames
  2. names2StatementListItemVarDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Declaration
  1. 返回一个新的空列表
VariableStatement : var VariableDeclarationList ;
  1. 返回 VariableDeclarationListBoundNames
IfStatement : if ( Expression ) Statement else Statement
  1. names1 为第一个 StatementVarDeclaredNames
  2. names2 为第二个 StatementVarDeclaredNames
  3. 返回 names1names2列表连接
IfStatement : if ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 StatementVarDeclaredNames
WhileStatement : while ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarDeclaredNames
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. names1VariableDeclarationListBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarDeclaredNames
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回 StatementVarDeclaredNames
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. names1ForBindingBoundNames
  2. names2StatementVarDeclaredNames
  3. 返回 names1names2列表连接

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarDeclaredNames
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarDeclaredNames
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 names1 为第一个 CaseClausesVarDeclaredNames
  2. 否则,令 names1 为一个新的空列表
  3. names2DefaultClauseVarDeclaredNames
  4. 如果第二个 CaseClauses 存在,令 names3 为第二个 CaseClausesVarDeclaredNames
  5. 否则,令 names3 为一个新的空列表
  6. 返回 names1names2names3列表连接
CaseClauses : CaseClauses CaseClause
  1. names1CaseClausesVarDeclaredNames
  2. names2CaseClauseVarDeclaredNames
  3. 返回 names1names2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,则返回 StatementListVarDeclaredNames
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarDeclaredNames
LabelledItem : FunctionDeclaration
  1. 返回一个新的空列表
TryStatement : try Block Catch
  1. names1BlockVarDeclaredNames
  2. names2CatchVarDeclaredNames
  3. 返回 names1names2列表连接
TryStatement : try Block Finally
  1. names1BlockVarDeclaredNames
  2. names2FinallyVarDeclaredNames
  3. 返回 names1names2列表连接
TryStatement : try Block Catch Finally
  1. names1BlockVarDeclaredNames
  2. names2CatchVarDeclaredNames
  3. names3FinallyVarDeclaredNames
  4. 返回 names1names2names3列表连接
Catch : catch ( CatchParameter ) Block
  1. 返回 BlockVarDeclaredNames
FunctionStatementList : [空]
  1. 返回一个新的空列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ConciseBody : ExpressionBody
  1. 返回一个新的空列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空列表
Script : [空]
  1. 返回一个新的空列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarDeclaredNames
ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListVarDeclaredNames
  2. names2ModuleItemVarDeclaredNames
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空列表
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,则返回 ExportDeclarationBoundNames
  2. 返回一个新的空列表

8.2.7 静态语义:VarScopedDeclarations

语法导向操作 VarScopedDeclarations 不接受参数,返回一个包含 解析节点列表。它针对以下产生式分段定义:

Statement : EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement
  1. 返回一个新的空列表
Block : { }
  1. 返回一个新的空列表
StatementList : StatementList StatementListItem
  1. declarations1StatementListVarScopedDeclarations
  2. declarations2StatementListItemVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Declaration
  1. 返回一个新的空列表
VariableDeclarationList : VariableDeclaration
  1. 返回 « VariableDeclaration »。
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. declarations1VariableDeclarationListVarScopedDeclarations
  2. 返回 declarations1 和 « VariableDeclaration » 的 列表连接
IfStatement : if ( Expression ) Statement else Statement
  1. declarations1 为第一个 StatementVarScopedDeclarations
  2. declarations2 为第二个 StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
IfStatement : if ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回 StatementVarScopedDeclarations
WhileStatement : while ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarScopedDeclarations
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. declarations1VariableDeclarationListVarScopedDeclarations
  2. declarations2StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回 StatementVarScopedDeclarations
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回 StatementVarScopedDeclarations
ForInOfStatement : for ( var ForBinding in Expression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement
  1. declarations1 为 « ForBinding »。
  2. declarations2StatementVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接

本节由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回 StatementVarScopedDeclarations
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlockVarScopedDeclarations
CaseBlock : { }
  1. 返回一个新的空列表
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,令 declarations1 为第一个 CaseClausesVarScopedDeclarations
  2. 否则,令 declarations1 为一个新的空列表
  3. declarations2DefaultClauseVarScopedDeclarations
  4. 如果第二个 CaseClauses 存在,令 declarations3 为第二个 CaseClausesVarScopedDeclarations
  5. 否则,令 declarations3 为一个新的空列表
  6. 返回 declarations1declarations2declarations3列表连接
CaseClauses : CaseClauses CaseClause
  1. declarations1CaseClausesVarScopedDeclarations
  2. declarations2CaseClauseVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回 StatementListVarScopedDeclarations
  2. 返回一个新的空列表
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回 StatementListVarScopedDeclarations
  2. 返回一个新的空列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回一个新的空列表
TryStatement : try Block Catch
  1. declarations1BlockVarScopedDeclarations
  2. declarations2CatchVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
TryStatement : try Block Finally
  1. declarations1BlockVarScopedDeclarations
  2. declarations2FinallyVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
TryStatement : try Block Catch Finally
  1. declarations1BlockVarScopedDeclarations
  2. declarations2CatchVarScopedDeclarations
  3. declarations3FinallyVarScopedDeclarations
  4. 返回 declarations1declarations2declarations3列表连接
Catch : catch ( CatchParameter ) Block
  1. 返回 BlockVarScopedDeclarations
FunctionStatementList : [空]
  1. 返回一个新的空 列表
FunctionStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ClassStaticBlockStatementList : [空]
  1. 返回一个新的空 列表
ClassStaticBlockStatementList : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
ConciseBody : ExpressionBody
  1. 返回一个新的空 列表
AsyncConciseBody : ExpressionBody
  1. 返回一个新的空 列表
Script : [空]
  1. 返回一个新的空 列表
ScriptBody : StatementList
  1. 返回 StatementListTopLevelVarScopedDeclarations
Module : [空]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. declarations1ModuleItemListVarScopedDeclarations
  2. declarations2ModuleItemVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
ModuleItem : ImportDeclaration
  1. 返回一个新的空 列表
ModuleItem : ExportDeclaration
  1. 如果 ExportDeclarationexport VariableStatement,返回 VariableStatementVarScopedDeclarations
  2. 返回一个新的空 列表

8.2.8 静态语义:TopLevelLexicallyDeclaredNames

语法导向操作 TopLevelLexicallyDeclaredNames 不接受参数并返回一个字符串的 列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. names1StatementListTopLevelLexicallyDeclaredNames
  2. names2StatementListItemTopLevelLexicallyDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Statement
  1. 返回一个新的空 列表
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. 返回一个新的空 列表
  2. 返回 DeclarationBoundNames
注意

在函数或脚本的顶层,函数声明被当作 var 声明处理,而不是词法声明。

8.2.9 静态语义:TopLevelLexicallyScopedDeclarations

语法导向操作 TopLevelLexicallyScopedDeclarations 不接受参数并返回一个 解析节点列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListTopLevelLexicallyScopedDeclarations
  2. declarations2StatementListItemTopLevelLexicallyScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 返回一个新的空 列表
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. 返回一个新的空 列表
  2. 返回 « Declaration »。

8.2.10 静态语义:TopLevelVarDeclaredNames

语法导向操作 TopLevelVarDeclaredNames 不接受参数并返回一个字符串的 列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. names1StatementListTopLevelVarDeclaredNames
  2. names2StatementListItemTopLevelVarDeclaredNames
  3. 返回 names1names2列表连接
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. 返回 HoistableDeclarationBoundNames
  2. 返回一个新的空 列表
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarDeclaredNames
  2. 返回 StatementVarDeclaredNames
注意

在函数或脚本的顶层,内部函数声明被当作 var 声明处理。

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarDeclaredNames
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarDeclaredNames
  2. 返回 StatementVarDeclaredNames
LabelledItem : FunctionDeclaration
  1. 返回 FunctionDeclarationBoundNames

8.2.11 静态语义:TopLevelVarScopedDeclarations

语法导向操作 TopLevelVarScopedDeclarations 不接受参数并返回一个 解析节点列表。它在以下产生式上分段定义:

StatementList : StatementList StatementListItem
  1. declarations1StatementListTopLevelVarScopedDeclarations
  2. declarations2StatementListItemTopLevelVarScopedDeclarations
  3. 返回 declarations1declarations2列表连接
StatementListItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
StatementListItem : Declaration
  1. 如果 Declaration Declaration : HoistableDeclaration ,那么
    1. declarationHoistableDeclarationDeclarationPart
    2. 返回 « declaration »。
  2. 返回一个新的空 列表
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItemTopLevelVarScopedDeclarations
LabelledItem : Statement
  1. 如果 Statement Statement : LabelledStatement ,返回 StatementTopLevelVarScopedDeclarations
  2. 返回 StatementVarScopedDeclarations
LabelledItem : FunctionDeclaration
  1. 返回 « FunctionDeclaration »。

8.3 标签

8.3.1 静态语义:ContainsDuplicateLabels

语法导向操作 ContainsDuplicateLabels 接受参数 labelSet(一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasDuplicates 为以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 StatementListItemContainsDuplicateLabels
IfStatement : if ( Expression ) Statement else Statement
  1. hasDuplicate 为以参数 labelSet 调用第一个 StatementContainsDuplicateLabels
  2. 如果 hasDuplicatetrue,返回 true
  3. 返回以参数 labelSet 调用第二个 StatementContainsDuplicateLabels
IfStatement : if ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
注意

此部分由附录 B.3.5 扩展。

WithStatement : with ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsDuplicateLabels
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 labelSet 调用 CaseBlockContainsDuplicateLabels
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 labelSet 调用第一个 CaseClausesContainsDuplicateLabelstrue,返回 true
  2. 如果以参数 labelSet 调用 DefaultClauseContainsDuplicateLabelstrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 labelSet 调用第二个 CaseClausesContainsDuplicateLabels
CaseClauses : CaseClauses CaseClause
  1. hasDuplicates 为以参数 labelSet 调用 CaseClausesContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 CaseClauseContainsDuplicateLabels
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsDuplicateLabels
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. 如果 labelSet 包含 label,返回 true
  3. newLabelSetlabelSet 和 « label » 的 列表连接
  4. 返回以参数 newLabelSet 调用 LabelledItemContainsDuplicateLabels
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasDuplicates 为以参数 labelSet 调用 BlockContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 CatchContainsDuplicateLabels
TryStatement : try Block Finally
  1. hasDuplicates 为以参数 labelSet 调用 BlockContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsDuplicateLabels
TryStatement : try Block Catch Finally
  1. 如果以参数 labelSet 调用 BlockContainsDuplicateLabelstrue,返回 true
  2. 如果以参数 labelSet 调用 CatchContainsDuplicateLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsDuplicateLabels
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 labelSet 调用 BlockContainsDuplicateLabels
FunctionStatementList : [空]
  1. 返回 false
ClassStaticBlockStatementList : [空]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasDuplicates 为以参数 labelSet 调用 ModuleItemListContainsDuplicateLabels
  2. 如果 hasDuplicatestrue,返回 true
  3. 返回以参数 labelSet 调用 ModuleItemContainsDuplicateLabels
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.2 静态语义:ContainsUndefinedBreakTarget

语法导向操作 ContainsUndefinedBreakTarget 接受参数 labelSet (一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
StatementList : StatementList StatementListItem
  1. hasUndefinedLabels 为以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 StatementListItemContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为以参数 labelSet 调用第一个 StatementContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用第二个 StatementContainsUndefinedBreakTarget
IfStatement : if ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget

本节由附录 B.3.5 扩展。

BreakStatement : break ;
  1. 返回 false
BreakStatement : break LabelIdentifier ;
  1. 如果 labelSet 不包含 LabelIdentifierStringValue,返回 true
  2. 返回 false
WithStatement : with ( Expression ) Statement
  1. 返回以参数 labelSet 调用 StatementContainsUndefinedBreakTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 labelSet 调用 CaseBlockContainsUndefinedBreakTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 labelSet 调用第一个 CaseClausesContainsUndefinedBreakTargettrue,返回 true
  2. 如果以参数 labelSet 调用 DefaultClauseContainsUndefinedBreakTargettrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 labelSet 调用第二个 CaseClausesContainsUndefinedBreakTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabels 为以参数 labelSet 调用 CaseClausesContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 CaseClauseContainsUndefinedBreakTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 labelSet 调用 StatementListContainsUndefinedBreakTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. 返回以参数 newLabelSet 调用 LabelledItemContainsUndefinedBreakTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabels 为以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 CatchContainsUndefinedBreakTarget
TryStatement : try Block Finally
  1. hasUndefinedLabels 为以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsUndefinedBreakTarget
TryStatement : try Block Catch Finally
  1. 如果以参数 labelSet 调用 BlockContainsUndefinedBreakTargettrue,返回 true
  2. 如果以参数 labelSet 调用 CatchContainsUndefinedBreakTargettrue,返回 true
  3. 返回以参数 labelSet 调用 FinallyContainsUndefinedBreakTarget
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 labelSet 调用 BlockContainsUndefinedBreakTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabels 为以参数 labelSet 调用 ModuleItemListContainsUndefinedBreakTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 labelSet 调用 ModuleItemContainsUndefinedBreakTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.3.3 静态语义:ContainsUndefinedContinueTarget

语法导向操作 ContainsUndefinedContinueTarget 接受参数 iterationSet(一个字符串的 列表)和 labelSet(一个字符串的 列表)并返回一个布尔值。它在以下产生式上分段定义:

Statement : VariableStatement EmptyStatement ExpressionStatement BreakStatement ReturnStatement ThrowStatement DebuggerStatement Block : { } StatementListItem : Declaration
  1. 返回 false
Statement : BlockStatement
  1. 返回以参数 iterationSet 和 « » 调用 BlockStatementContainsUndefinedContinueTarget
BreakableStatement : IterationStatement
  1. newIterationSetiterationSetlabelSet列表连接
  2. 返回以参数 newIterationSet 和 « » 调用 IterationStatementContainsUndefinedContinueTarget
StatementList : StatementList StatementListItem
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 StatementListItemContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement else Statement
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用第一个 StatementContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用第二个 StatementContainsUndefinedContinueTarget
IfStatement : if ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
DoWhileStatement : do Statement while ( Expression ) ;
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
WhileStatement : while ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget

本节由附录 B.3.5 扩展。

ContinueStatement : continue ;
  1. 返回 false
ContinueStatement : continue LabelIdentifier ;
  1. 如果 iterationSet 不包含 LabelIdentifierStringValue,返回 true
  2. 返回 false
WithStatement : with ( Expression ) Statement
  1. 返回以参数 iterationSet 和 « » 调用 StatementContainsUndefinedContinueTarget
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回以参数 iterationSet 和 « » 调用 CaseBlockContainsUndefinedContinueTarget
CaseBlock : { }
  1. 返回 false
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. 如果第一个 CaseClauses 存在,那么
    1. 如果以参数 iterationSet 和 « » 调用第一个 CaseClausesContainsUndefinedContinueTargettrue,返回 true
  2. 如果以参数 iterationSet 和 « » 调用 DefaultClauseContainsUndefinedContinueTargettrue,返回 true
  3. 如果第二个 CaseClauses 不存在,返回 false
  4. 返回以参数 iterationSet 和 « » 调用第二个 CaseClausesContainsUndefinedContinueTarget
CaseClauses : CaseClauses CaseClause
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 CaseClausesContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 CaseClauseContainsUndefinedContinueTarget
CaseClause : case Expression : StatementListopt
  1. 如果 StatementList 存在,返回以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 返回 false
DefaultClause : default : StatementListopt
  1. 如果 StatementList 存在,返回以参数 iterationSet 和 « » 调用 StatementListContainsUndefinedContinueTarget
  2. 返回 false
LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. 返回以参数 iterationSetnewLabelSet 调用 LabelledItemContainsUndefinedContinueTarget
LabelledItem : FunctionDeclaration
  1. 返回 false
TryStatement : try Block Catch
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 CatchContainsUndefinedContinueTarget
TryStatement : try Block Finally
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 FinallyContainsUndefinedContinueTarget
TryStatement : try Block Catch Finally
  1. 如果以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTargettrue,返回 true
  2. 如果以参数 iterationSet 和 « » 调用 CatchContainsUndefinedContinueTargettrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 FinallyContainsUndefinedContinueTarget
Catch : catch ( CatchParameter ) Block
  1. 返回以参数 iterationSet 和 « » 调用 BlockContainsUndefinedContinueTarget
FunctionStatementList : [empty]
  1. 返回 false
ClassStaticBlockStatementList : [empty]
  1. 返回 false
ModuleItemList : ModuleItemList ModuleItem
  1. hasUndefinedLabels 为以参数 iterationSet 和 « » 调用 ModuleItemListContainsUndefinedContinueTarget
  2. 如果 hasUndefinedLabelstrue,返回 true
  3. 返回以参数 iterationSet 和 « » 调用 ModuleItemContainsUndefinedContinueTarget
ModuleItem : ImportDeclaration ExportDeclaration
  1. 返回 false

8.4 函数名推断

8.4.1 静态语义:HasName

语法导向操作 HasName 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 如果 exprIsFunctionDefinitionfalse,返回 false
  3. 返回 exprHasName
FunctionExpression : function ( FormalParameters ) { FunctionBody } GeneratorExpression : function * ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody } ArrowFunction : ArrowParameters => ConciseBody AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody ClassExpression : class ClassTail
  1. 返回 false
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody } GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } ClassExpression : class BindingIdentifier ClassTail
  1. 返回 true

8.4.2 静态语义:IsFunctionDefinition

语法导向操作 IsFunctionDefinition 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 exprIsFunctionDefinition
PrimaryExpression : this IdentifierReference Literal ArrayLiteral ObjectLiteral RegularExpressionLiteral TemplateLiteral MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression AwaitExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression LogicalANDExpression : LogicalANDExpression && BitwiseORExpression LogicalORExpression : LogicalORExpression || LogicalANDExpression CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression AssignmentExpression : YieldExpression LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression Expression : Expression , AssignmentExpression
  1. 返回 false
AssignmentExpression : ArrowFunction AsyncArrowFunction FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody } ClassExpression : class BindingIdentifieropt ClassTail
  1. 返回 true

8.4.3 静态语义:IsAnonymousFunctionDefinition ( expr )

抽象操作 IsAnonymousFunctionDefinition 接受参数 expr(一个 AssignmentExpression 解析节点、一个 Initializer 解析节点,或一个 Expression 解析节点)并返回一个布尔值。它确定其参数是否为不绑定名称的函数定义。当被调用时执行以下步骤:

  1. 如果 exprIsFunctionDefinitionfalse,返回 false
  2. hasNameexprHasName
  3. 如果 hasNametrue,返回 false
  4. 返回 true

8.4.4 静态语义:IsIdentifierRef

语法导向操作 IsIdentifierRef 不接受任何参数并返回一个布尔值。它在以下产生式上分段定义:

PrimaryExpression : IdentifierReference
  1. 返回 true
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CoverParenthesizedExpressionAndArrowParameterList MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false

8.4.5 运行时语义:NamedEvaluation

语法导向操作 NamedEvaluation 接受参数 name(一个 属性键或一个 私有名称)并返回要么 包含 函数对象的正常完成,要么 中断完成。它在以下产生式上分段定义:

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 ? expr 以参数 name 执行的 NamedEvaluation
ParenthesizedExpression : ( Expression )
  1. 断言IsAnonymousFunctionDefinition(Expression) 是 true
  2. 返回 ? Expression 以参数 name 执行的 NamedEvaluation
FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpression 以参数 name 执行的 InstantiateOrdinaryFunctionExpression
GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpression 以参数 name 执行的 InstantiateGeneratorFunctionExpression
AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpression 以参数 name 执行的 InstantiateAsyncGeneratorFunctionExpression
AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpression 以参数 name 执行的 InstantiateAsyncFunctionExpression
ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunction 以参数 name 执行的 InstantiateArrowFunctionExpression
AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunction 以参数 name 执行的 InstantiateAsyncArrowFunctionExpression
ClassExpression : class ClassTail
  1. value 为 ? ClassTail 以参数 undefinedname 执行的 ClassDefinitionEvaluation
  2. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  3. 返回 value

8.5 包含 (Contains)

8.5.1 静态语义:包含 (Contains)

语法导向操作 包含 (Contains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。

本规范中所有未在下面列出的语法产生式备选都隐式具有以下 包含 (Contains) 的默认定义:

  1. 对于此 解析节点 的每个子节点 child,执行:
    1. 如果 childsymbol 的实例,返回 true
    2. 如果 child 是一个非终结符的实例,则:
      1. containedchild 包含 symbol 的结果。
      2. 如果 containedtrue,返回 true
  2. 返回 false
函数声明 : function 绑定标识符 ( 形式参数 ) { 函数体 } function ( 形式参数 ) { 函数体 } 函数表达式 : function 绑定标识符opt ( 形式参数 ) { 函数体 } 生成器声明 : function * 绑定标识符 ( 形式参数 ) { 生成器体 } function * ( 形式参数 ) { 生成器体 } 生成器表达式 : function * 绑定标识符opt ( 形式参数 ) { 生成器体 } 异步生成器声明 : async function * 绑定标识符 ( 形式参数 ) { 异步生成器体 } async function * ( 形式参数 ) { 异步生成器体 } 异步生成器表达式 : async function * 绑定标识符opt ( 形式参数 ) { 异步生成器体 } 异步函数声明 : async function 绑定标识符 ( 形式参数 ) { 异步函数体 } async function ( 形式参数 ) { 异步函数体 } 异步函数表达式 : async function 绑定标识符opt ( 形式参数 ) { 异步函数体 }
  1. 返回 false
注 1

依赖于子结构的静态语义规则通常不深入函数定义。

类尾 : 类继承opt { 类体 }
  1. 如果 symbol类体,返回 true
  2. 如果 symbol类继承,则:
    1. 如果 类继承 存在,返回 true;否则返回 false
  3. 如果 类继承 存在,则:
    1. 如果 类继承 包含 symboltrue,返回 true
  4. 返回以 symbol 为参数的 类体计算属性包含 的结果。
注 2

依赖于子结构的静态语义规则通常不深入类体,除了 属性名

类静态块 : static { 类静态块体 }
  1. 返回 false
注 3

依赖于子结构的静态语义规则通常不深入 static 初始化块。

箭头函数 : 箭头参数 => 简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. 如果 箭头参数 包含 symboltrue,返回 true
  3. 返回 简洁体 包含 symbol
箭头参数 : 覆盖带括号的表达式和箭头参数列表
  1. formals 为被 覆盖带括号的表达式和箭头参数列表 覆盖箭头形式参数
  2. 返回 formals 包含 symbol
异步箭头函数 : async 异步箭头绑定标识符 => 异步简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. 返回 异步简洁体 包含 symbol
异步箭头函数 : 覆盖调用表达式和异步箭头头部 => 异步简洁体
  1. 如果 symbol 不是 NewTargetSuperPropertySuperCallsuperthis 之一,返回 false
  2. head 为被 覆盖调用表达式和异步箭头头部 覆盖异步箭头头部
  3. 如果 head 包含 symboltrue,返回 true
  4. 返回 异步简洁体 包含 symbol
注 4

包含 (Contains) 用于检测 箭头函数异步箭头函数new.targetthissuper 的使用情况。

属性定义 : 方法定义
  1. 如果 symbol方法定义,返回 true
  2. 返回以 symbol 为参数的 方法定义计算属性包含 的结果。
字面量属性名 : 标识符名称
  1. 返回 false
成员表达式 : 成员表达式 . 标识符名称
  1. 如果 成员表达式 包含 symboltrue,返回 true
  2. 返回 false
Super属性 : super . 标识符名称
  1. 如果 symbol保留字 super,返回 true
  2. 返回 false
调用表达式 : 调用表达式 . 标识符名称
  1. 如果 调用表达式 包含 symboltrue,返回 true
  2. 返回 false
可选链 : ?. 标识符名称
  1. 返回 false
可选链 : 可选链 . 标识符名称
  1. 如果 可选链 包含 symboltrue,返回 true
  2. 返回 false

8.5.2 静态语义:计算属性包含 (ComputedPropertyContains)

语法导向操作 计算属性包含 (ComputedPropertyContains) 接受参数 symbol (一个语法符号) 并返回一个布尔值。它在以下产生式中分段定义:

类元素名称 : 私有标识符 属性名 : 字面量属性名
  1. 返回 false
属性名 : 计算属性名
  1. 返回 计算属性名 包含 symbol 的结果。
方法定义 : 类元素名称 ( 唯一形式参数 ) { 函数体 } get 类元素名称 ( ) { 函数体 } set 类元素名称 ( 属性设置器参数列表 ) { 函数体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
生成器方法 : * 类元素名称 ( 唯一形式参数 ) { 生成器体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
异步生成器方法 : async * 类元素名称 ( 唯一形式参数 ) { 异步生成器体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
类元素列表 : 类元素列表 类元素
  1. inList 为以 symbol 为参数的 类元素列表计算属性包含
  2. 如果 inListtrue,返回 true
  3. 返回以 symbol 为参数的 类元素计算属性包含 的结果。
类元素 : 类静态块
  1. 返回 false
类元素 : ;
  1. 返回 false
异步方法 : async 类元素名称 ( 唯一形式参数 ) { 异步函数体 }
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。
字段定义 : 类元素名称 初始化器opt
  1. 返回以 symbol 为参数的 类元素名称计算属性包含 的结果。

8.6 杂项

这些操作在规范中的多个地方使用。

8.6.1 运行时语义:InstantiateFunctionObject

语法导向操作 InstantiateFunctionObject 接收参数 env (一个 环境记录) 和 privateEnv (一个 私有环境记录null),并返回一个 ECMAScript 函数对象。它在以下产生式上分段定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody }
  1. 返回 InstantiateOrdinaryFunctionObject,其参数为 FunctionDeclaration,以及参数 envprivateEnv
GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody }
  1. 返回 InstantiateGeneratorFunctionObject,其参数为 GeneratorDeclaration,以及参数 envprivateEnv
AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 InstantiateAsyncGeneratorFunctionObject,其参数为 AsyncGeneratorDeclaration,以及参数 envprivateEnv
AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 InstantiateAsyncFunctionObject,其参数为 AsyncFunctionDeclaration,以及参数 envprivateEnv

8.6.2 运行时语义:BindingInitialization

语法导向操作 BindingInitialization 接受参数 value(一个 ECMAScript 语言值)和 environment(一个 环境记录undefined),并返回一个 包含 unused 的正常完成,或者一个 异常完成

注意

undefined 作为 environment 传递,以指示应使用 PutValue 操作来分配初始化值。对于 var 语句和某些 非严格函数 的形式参数列表(参见 10.2.11)就是这种情况。在这些情况下,词法绑定会在其初始化程序的评估之前被提升和预初始化。

它在以下产生式上分段定义:

BindingIdentifier : Identifier
  1. nameIdentifierStringValue
  2. 返回 ? InitializeBoundName(name, value, environment).
BindingIdentifier : yield
  1. 返回 ? InitializeBoundName("yield", value, environment).
BindingIdentifier : await
  1. 返回 ? InitializeBoundName("await", value, environment).
BindingPattern : ObjectBindingPattern
  1. 执行 ? RequireObjectCoercible(value).
  2. 返回 ? BindingInitialization(ObjectBindingPattern with arguments valueenvironment.
BindingPattern : ArrayBindingPattern
  1. iteratorRecord 为 ? GetIterator(value, sync).
  2. resultCompletion(IteratorBindingInitialization of ArrayBindingPattern with arguments iteratorRecordenvironment).
  3. 如果 iteratorRecord.[[Done]]false,则返回 ? IteratorClose(iteratorRecord, result).
  4. 返回 ? result.
ObjectBindingPattern : { }
  1. 返回 unused.
ObjectBindingPattern : { BindingPropertyList } { BindingPropertyList , }
  1. 执行 ? PropertyBindingInitialization(BindingPropertyList with arguments valueenvironment.
  2. 返回 unused.
ObjectBindingPattern : { BindingRestProperty }
  1. excludedNames 为一个新的空 列表
  2. 返回 ? RestBindingInitialization(BindingRestProperty with arguments value, environment, 和 excludedNames.
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. excludedNames 为 ? PropertyBindingInitialization(BindingPropertyList with arguments valueenvironment.
  2. 返回 ? RestBindingInitialization(BindingRestProperty with arguments value, environment, 和 excludedNames.

8.6.2.1 InitializeBoundName ( name, value, environment )

抽象操作 InitializeBoundName 接受参数 name(一个字符串)、value(一个 ECMAScript 语言值)和 environment(一个 环境记录undefined),并返回一个 包含 unused 的正常完成,或者一个 异常完成。调用时,它执行以下步骤:

  1. 如果 environment 不是 undefined,则:
    1. 执行 ! environment.InitializeBinding(name, value).
    2. 返回 unused.
  2. 否则:
    1. lhs 为 ? ResolveBinding(name).
    2. 返回 ? PutValue(lhs, value).

8.6.3 运行时语义:IteratorBindingInitialization

语法导向操作 IteratorBindingInitialization 接受参数 iteratorRecord(一个迭代器记录)和 environment (一个环境记录undefined),并返回包含 unused正常完成异常完成

environment 传递 undefined 时,表示应该使用PutValue 操作来分配初始化值。这是非严格函数的形式参数列表的情况。在这种情况下,形式参数绑定被预初始化,以处理具有相同名称的多个参数的可能性。

它在以下产生式上分段定义:

ArrayBindingPattern : [ ]
  1. 返回 unused
ArrayBindingPattern : [ Elision ]
  1. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 如果 Elision 存在,则
    1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  2. 返回 ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment
ArrayBindingPattern : [ BindingElementList , Elision ]
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 返回 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 如果 Elision 存在,则
    1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  3. 返回 ? IteratorBindingInitialization of BindingRestElement with arguments iteratorRecord and environment
BindingElementList : BindingElementList , BindingElisionElement
  1. 执行 ? IteratorBindingInitialization of BindingElementList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of BindingElisionElement with arguments iteratorRecord and environment
BindingElisionElement : Elision BindingElement
  1. 执行 ? IteratorDestructuringAssignmentEvaluation of Elision with argument iteratorRecord
  2. 返回 ? IteratorBindingInitialization of BindingElement with arguments iteratorRecord and environment
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId, environment)。
  3. vundefined
  4. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 vnext
  5. 如果 Initializer 存在且 vundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? NamedEvaluation of Initializer with argument bindingId
    2. 否则,
      1. defaultValue 为 ? Evaluation of Initializer
      2. 设置 v 为 ? GetValue(defaultValue)。
  6. 如果 environmentundefined,则返回 ? PutValue(lhs, v)。
  7. 返回 ? InitializeReferencedBinding(lhs, v)。
BindingElement : BindingPattern Initializeropt
  1. vundefined
  2. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 vnext
  3. 如果 Initializer 存在且 vundefined,则
    1. defaultValue 为 ? Evaluation of Initializer
    2. 设置 v 为 ? GetValue(defaultValue)。
  4. 返回 ? BindingInitialization of BindingPattern with arguments v and environment
BindingRestElement : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValue, environment)。
  2. A 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. 设置 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 如果 environmentundefined,则返回 ? PutValue(lhs, A)。
      2. 返回 ? InitializeReferencedBinding(lhs, A)。
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
    5. 设置 nn + 1。
BindingRestElement : ... BindingPattern
  1. A 为 ! ArrayCreate(0)。
  2. n 为 0。
  3. 重复,
    1. nextdone
    2. 如果 iteratorRecord.[[Done]]false,则
      1. 设置 next 为 ? IteratorStepValue(iteratorRecord)。
    3. 如果 nextdone,则
      1. 返回 ? BindingInitialization of BindingPattern with arguments A and environment
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
    5. 设置 nn + 1。
FormalParameters : [empty]
  1. 返回 unused
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 执行 ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of FunctionRestParameter with arguments iteratorRecord and environment
FormalParameterList : FormalParameterList , FormalParameter
  1. 执行 ? IteratorBindingInitialization of FormalParameterList with arguments iteratorRecord and environment
  2. 返回 ? IteratorBindingInitialization of FormalParameter with arguments iteratorRecord and environment
ArrowParameters : BindingIdentifier
  1. vundefined
  2. 断言iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 设置 vnext
  5. 返回 ? BindingInitialization of BindingIdentifier with arguments v and environment
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 ? IteratorBindingInitialization of formals with arguments iteratorRecord and environment
AsyncArrowBindingIdentifier : BindingIdentifier
  1. vundefined
  2. 断言iteratorRecord.[[Done]]false
  3. next 为 ? IteratorStepValue(iteratorRecord)。
  4. 如果 next 不是 done,则
    1. 设置 vnext
  5. 返回 ? BindingInitialization of BindingIdentifier with arguments v and environment

8.6.4 静态语义:AssignmentTargetType

语法导向操作 AssignmentTargetType 不接受参数并返回 simpleinvalid。它在以下产生式上分段定义:

IdentifierReference : Identifier
  1. 如果 IsStrict(this IdentifierReference) 是 trueIdentifierStringValue"eval""arguments",返回 invalid
  2. 返回 simple
IdentifierReference : yield await CallExpression : CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MemberExpression . PrivateIdentifier
  1. 返回 simple
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 exprAssignmentTargetType
PrimaryExpression : this Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral CallExpression : CoverCallExpressionAndAsyncArrowHead SuperCall ImportCall CallExpression Arguments CallExpression TemplateLiteral NewExpression : new NewExpression MemberExpression : MemberExpression TemplateLiteral new MemberExpression Arguments NewTarget : new . target ImportMeta : import . meta LeftHandSideExpression : OptionalExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression AwaitExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression LogicalANDExpression : LogicalANDExpression && BitwiseORExpression LogicalORExpression : LogicalORExpression || LogicalANDExpression CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression Expression : Expression , AssignmentExpression
  1. 返回 invalid

8.6.5 静态语义:PropName

语法导向操作 PropName 不接受参数并返回一个字符串或 empty。它在以下产生式上分段定义:

PropertyDefinition : IdentifierReference
  1. 返回 IdentifierReferenceStringValue
PropertyDefinition : ... AssignmentExpression
  1. 返回 empty
PropertyDefinition : PropertyName : AssignmentExpression
  1. 返回 PropertyNamePropName
LiteralPropertyName : IdentifierName AttributeKey : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral AttributeKey : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
ComputedPropertyName : [ AssignmentExpression ]
  1. 返回 empty
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 ClassElementNamePropName
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 返回 ClassElementNamePropName
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementNamePropName
ClassElement : ClassStaticBlock
  1. 返回 empty
ClassElement : ;
  1. 返回 empty
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementNamePropName
FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementNamePropName
ClassElementName : PrivateIdentifier
  1. 返回 empty

9 可执行代码和执行上下文

9.1 环境记录

环境记录是一种规范类型, 用于定义标识符与特定变量和函数的关联,基于 ECMAScript代码的词法嵌套结构。通常环境记录与ECMAScript代码的某些特定语法结构相关联, 如函数声明块语句try语句catch子句。每次求值这样的代码时, 都会创建一个新的环境记录来记录该代码创建的标识符绑定。

每个环境记录都有一个[[OuterEnv]]字段,它要么是 null,要么是对外部环境记录的引用。这用于建模环境记录值的逻辑嵌套。 (内部)环境记录的外部引用是对逻辑上围绕内部环境记录的环境记录的引用。 外部环境记录当然可能有自己的外部环境记录。一个环境记录可以作为多个内部环境记录的外部环境。 例如,如果一个函数声明 包含两个嵌套的函数声明, 那么每个嵌套函数的环境记录都将以周围函数的当前求值的环境记录作为其外部环境记录。

环境记录纯粹是规范机制,不需要对应于ECMAScript实现的任何特定构件。 ECMAScript程序不可能直接访问或操作这样的值。

9.1.1 环境记录类型层次结构

环境记录可以看作存在于一个简单的面向对象层次结构中, 其中环境记录是一个 抽象类,有三个具体子类:声明式环境记录对象环境记录全局环境记录函数环境记录模块环境记录声明式环境记录的子类。

环境记录抽象类 包含表16中定义的抽象规范方法。 这些抽象方法对于每个具体子类都有不同的具体算法。

表16:环境记录的抽象方法
方法 目的
HasBinding(N) 确定环境记录 是否具有字符串值N的绑定。如果有则返回 true,如果没有则返回false
CreateMutableBinding(N, D) 环境记录中 创建一个新的但未初始化的可变绑定。 字符串值N是绑定名称的文本。如果布尔参数Dtrue,则绑定可以随后被删除。
CreateImmutableBinding(N, S) 环境记录中 创建一个新的但未初始化的不可变绑定。 字符串值N是绑定名称的文本。如果Strue,那么在初始化后尝试设置它时 总是会抛出异常,无论引用该绑定的操作的严格模式设置如何。
InitializeBinding(N, V) 设置环境记录中 已存在但未初始化的绑定的值。 字符串值N是绑定名称的文本。V是 绑定的值,是任何ECMAScript语言类型的值。
SetMutableBinding(N, V, S) 设置环境记录中 已存在的可变绑定的值。 字符串值N是绑定名称的文本。V是 绑定的值,可能是任何ECMAScript语言类型的值。S是布尔值标志。如果Strue且绑定无法设置,则抛出 TypeError异常。
GetBindingValue(N, S) 环境记录返回 已存在绑定的值。 字符串值N是绑定名称的文本。S 用于标识源自严格模式代码或 其他需要严格模式引用语义的引用。如果Strue且绑定不存在,则抛出 ReferenceError异常。如果绑定存在但未初始化, 则抛出ReferenceError,无论S的值如何。
DeleteBinding(N) 环境记录删除绑定。字符串值N是 绑定名称的文本。如果N的绑定存在,则移除绑定并 返回true。如果绑定存在但无法移除, 则返回false。如果绑定不存在,则返回 true
HasThisBinding() 确定环境记录 是否建立this绑定。如果建立则返回true, 如果不建立则返回false
HasSuperBinding() 确定环境记录 是否建立super方法绑定。如果建立则返回 true,如果不建立则返回false。 如果返回true,则暗示环境记录函数环境记录, 但反向推导不成立。
WithBaseObject() 如果此环境记录with语句关联,则返回with对象。 否则,返回undefined

9.1.1.1 声明式环境记录

每个声明式环境记录都与包含变量、常量、let、类、模块、导入和/或函数声明的ECMAScript程序作用域相关联。声明式环境记录绑定其作用域内包含的声明所定义的标识符集合。

9.1.1.1.1 HasBinding ( N )

声明式环境记录 envRec的HasBinding具体方法接受参数N (字符串)并返回包含布尔值的正常完成。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:

  1. 如果envRec具有N的绑定,返回 true
  2. 返回false

9.1.1.1.2 CreateMutableBinding ( N, D )

声明式环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串) 和D(布尔值)并返回包含 unused正常完成。它为名称N创建一个新的未初始化的可变绑定。此环境记录中不得已存在N的绑定。如果Dtrue,则新绑定被标记为可删除的。调用时执行以下步骤:

  1. 断言envRec不已经具有N的绑定。
  2. envRec中为N创建可变绑定并记录它是未初始化的。如果Dtrue,记录新创建的绑定可以被后续的DeleteBinding调用删除。
  3. 返回unused

9.1.1.1.3 CreateImmutableBinding ( N, S )

声明式环境记录 envRec的CreateImmutableBinding具体方法接受参数N(字符串) 和S(布尔值)并返回包含 unused正常完成。它为名称N创建一个新的未初始化的不可变绑定。此环境记录中不得已存在N的绑定。如果Strue,则新绑定被标记为严格绑定。调用时执行以下步骤:

  1. 断言envRec不已经具有N的绑定。
  2. envRec中为N创建不可变绑定并记录它是未初始化的。如果Strue,记录新创建的绑定是严格绑定。
  3. 返回unused

9.1.1.1.4 InitializeBinding ( N, V )

声明式环境记录 envRec的InitializeBinding具体方法接受参数N(字符串) 和VECMAScript语言值) 并返回包含 unused正常完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值VN的未初始化绑定必须已经存在。调用时执行以下步骤:

  1. 断言envRec必须具有N的未初始化绑定。
  2. envRecN的绑定值设置为V
  3. 记录envRecN的绑定已被初始化。
  4. 返回unused

9.1.1.1.5 SetMutableBinding ( N, V, S )

声明式环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、 VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将名称为N的标识符的当前绑定的绑定值更改为值VN的绑定通常已经存在,但在罕见情况下可能不存在。如果绑定是不可变绑定,当Strue时抛出TypeError。调用时执行以下步骤:

  1. 如果envRec没有N的绑定,则
    1. 如果Strue,抛出ReferenceError异常。
    2. 执行! envRec.CreateMutableBinding(N, true)。
    3. 执行! envRec.InitializeBinding(N, V)。
    4. 返回unused
  2. 如果envRecN的绑定是严格绑定,将S设置为true
  3. 如果envRecN的绑定尚未初始化,则
    1. 抛出ReferenceError异常。
  4. 否则如果envRecN的绑定是可变绑定,则
    1. 将其绑定值更改为V
  5. 否则,
    1. 断言:这是尝试更改不可变绑定的值。
    2. 如果Strue,抛出TypeError异常。
  6. 返回unused

导致步骤1缺失绑定的ECMAScript代码示例是:

function f() { eval("var x; x = (delete x, 0);"); }

9.1.1.1.6 GetBindingValue ( N, S )

声明式环境记录 envRec的GetBindingValue具体方法接受参数N(字符串) 和S(布尔值)并返回包含ECMAScript语言值正常完成抛出完成。它返回名称为N的绑定标识符的值。如果绑定存在但未初始化,则抛出ReferenceError,无论S的值如何。调用时执行以下步骤:

  1. 断言envRec具有N的绑定。
  2. 如果envRecN的绑定是未初始化绑定,抛出ReferenceError异常。
  3. 返回envRec中当前绑定到N的值。

9.1.1.1.7 DeleteBinding ( N )

声明式环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:

  1. 断言envRec具有N的绑定。
  2. 如果envRecN的绑定无法删除,返回false
  3. envRec中移除N的绑定。
  4. 返回true

9.1.1.1.8 HasThisBinding ( )

声明式环境记录 envRec的HasThisBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

常规声明式环境记录(即既不是函数环境记录也不是模块环境记录的记录)不提供this绑定。

9.1.1.1.9 HasSuperBinding ( )

声明式环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

常规声明式环境记录(即既不是函数环境记录也不是模块环境记录的记录)不提供super绑定。

9.1.1.1.10 WithBaseObject ( )

声明式环境记录 envRec的WithBaseObject具体方法不接受参数并返回undefined。调用时执行以下步骤:

  1. 返回undefined

9.1.1.2 对象环境记录

每个对象环境记录 都与一个称为其绑定对象的对象相关联。对象环境记录绑定一组字符串标识符名称, 这些名称直接对应于其绑定对象的属性名称。不是标识符名称形式的字符串的属性键不包含在绑定标识符集合中。无论其[[Enumerable]]属性的设置如何,自有属性和继承属性都包含在集合中。由于属性可以动态地从对象中添加和删除,对象环境记录绑定的标识符集合可能会作为任何添加或删除属性操作的副作用而发生变化。作为这种副作用结果创建的任何绑定都被认为是可变绑定,即使相应属性的Writable属性是false。对象环境记录不存在不可变绑定。

with语句(14.11)创建的对象环境记录可以提供其绑定对象作为函数调用中使用的隐式this值。这种能力由布尔值[[IsWithEnvironment]]字段控制。

对象环境记录具有表17中列出的附加状态字段。

表17:对象环境记录的附加字段
字段名称 含义
[[BindingObject]] 一个对象 环境记录的绑定对象。
[[IsWithEnvironment]] 布尔值 指示此环境记录是否为with语句创建。

9.1.1.2.1 HasBinding ( N )

对象环境记录 envRec的HasBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它确定其关联的绑定对象是否具有名称为N的属性。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. foundBinding为? HasProperty(bindingObject, N)。
  3. 如果foundBindingfalse,返回false
  4. 如果envRec.[[IsWithEnvironment]]false,返回true
  5. unscopables为? Get(bindingObject, %Symbol.unscopables%)。
  6. 如果unscopables是对象,则
    1. blockedToBoolean(? Get(unscopables, N))。
    2. 如果blockedtrue,返回false
  7. 返回true

9.1.1.2.2 CreateMutableBinding ( N, D )

对象环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它在环境记录的关联绑定对象中创建一个名称为N的属性,并将其初始化为值undefined。如果Dtrue,新属性的[[Configurable]]属性设置为true;否则设置为false。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 执行? DefinePropertyOrThrow(bindingObject, N, PropertyDescriptor { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D })。
  3. 返回unused

通常envRec不会有N的绑定,但如果有,DefinePropertyOrThrow的语义可能导致现有绑定被替换或遮蔽,或导致返回异常完成

9.1.1.2.3 CreateImmutableBinding ( N, S )

对象环境记录的CreateImmutableBinding具体方法在本规范中从未使用。

9.1.1.2.4 InitializeBinding ( N, V )

对象环境记录 envRec的InitializeBinding具体方法接受参数N(字符串)和VECMAScript语言值) 并返回包含 unused正常完成抛出完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值V。调用时执行以下步骤:

  1. 执行? envRec.SetMutableBinding(N, V, false)。
  2. 返回unused

在本规范中,对对象环境记录的CreateMutableBinding的所有使用之后都紧跟相同名称的InitializeBinding调用。因此,本规范不显式跟踪对象环境记录中绑定的初始化状态。

9.1.1.2.5 SetMutableBinding ( N, V, S )

对象环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将环境记录关联绑定对象的名称为N的属性的值设置为值V。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. stillExists为? HasProperty(bindingObject, N)。
  3. 如果stillExistsfalseStrue,抛出ReferenceError异常。
  4. 执行? Set(bindingObject, N, V, S)。
  5. 返回unused

9.1.1.2.6 GetBindingValue ( N, S )

对象环境记录 envRec的GetBindingValue具体方法接受参数N(字符串)和S(布尔值) 并返回包含ECMAScript语言值正常完成抛出完成。它返回其关联绑定对象的名称为N的属性的值。该属性应该已经存在,但如果不存在,结果取决于S。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. value为? HasProperty(bindingObject, N)。
  3. 如果valuefalse,则
    1. 如果Sfalse,返回undefined;否则抛出ReferenceError异常。
  4. 返回? Get(bindingObject, N)。

9.1.1.2.7 DeleteBinding ( N )

对象环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它只能删除对应于环境对象的[[Configurable]]属性值为true的属性的绑定。调用时执行以下步骤:

  1. bindingObjectenvRec.[[BindingObject]]
  2. 返回? bindingObject.[[Delete]](N)。

9.1.1.2.8 HasThisBinding ( )

对象环境记录 envRec的HasThisBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

对象环境记录不提供this绑定。

9.1.1.2.9 HasSuperBinding ( )

对象环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

对象环境记录不提供super绑定。

9.1.1.2.10 WithBaseObject ( )

对象环境记录 envRec的WithBaseObject具体方法不接受参数并返回对象或undefined。调用时执行以下步骤:

  1. 如果envRec.[[IsWithEnvironment]]true,返回envRec.[[BindingObject]]
  2. 否则,返回undefined

9.1.1.3 函数环境记录

函数环境记录是一个声明式环境记录,用于表示函数的顶层作用域,如果函数不是箭头函数,则提供this绑定。如果函数不是箭头函数并且引用super,其函数环境记录还包含用于在函数内执行super方法调用的状态。

函数环境记录具有表18中列出的附加状态字段。

表18:函数环境记录的附加字段
字段名称 含义
[[ThisValue]] 一个ECMAScript语言值 这是用于此函数调用的this值。
[[ThisBindingStatus]] lexicalinitializeduninitialized 如果值是lexical,这是一个箭头函数,不具有本地this值。
[[FunctionObject]] 一个ECMAScript函数对象 调用导致创建此环境记录函数对象
[[NewTarget]] 一个构造函数undefined 如果此环境记录[[Construct]]内部方法创建,[[NewTarget]][[Construct]]newTarget参数的值。否则,其值为undefined

函数环境记录支持表16中列出的所有声明式环境记录方法,除了HasThisBinding和HasSuperBinding,所有这些方法都共享相同的规范。此外,函数环境记录支持表19中列出的方法:

表19:函数环境记录的附加方法
方法 目的
GetThisBinding() 返回此环境记录this绑定的值。如果this绑定尚未初始化,则抛出ReferenceError

9.1.1.3.1 BindThisValue ( envRec, V )

抽象操作BindThisValue接受参数envRec(一个函数环境记录)和V(一个ECMAScript语言值) 并返回包含 unused正常完成抛出完成。它设置envRec.[[ThisValue]]并记录它已被初始化。调用时执行以下步骤:

  1. 断言envRec.[[ThisBindingStatus]]不是lexical
  2. 如果envRec.[[ThisBindingStatus]]initialized,抛出ReferenceError异常。
  3. 设置envRec.[[ThisValue]]V
  4. 设置envRec.[[ThisBindingStatus]]initialized
  5. 返回unused

9.1.1.3.2 HasThisBinding ( )

函数环境记录 envRec的HasThisBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:

  1. 如果envRec.[[ThisBindingStatus]]lexical,返回false;否则,返回true

9.1.1.3.3 HasSuperBinding ( )

函数环境记录 envRec的HasSuperBinding具体方法不接受参数并返回布尔值。调用时执行以下步骤:

  1. 如果envRec.[[ThisBindingStatus]]lexical,返回false
  2. 如果envRec.[[FunctionObject]].[[HomeObject]]undefined,返回false;否则,返回true

9.1.1.3.4 GetThisBinding ( )

函数环境记录 envRec的GetThisBinding具体方法不接受参数并返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 断言envRec.[[ThisBindingStatus]]不是lexical
  2. 如果envRec.[[ThisBindingStatus]]uninitialized,抛出ReferenceError异常。
  3. 返回envRec.[[ThisValue]]

9.1.1.3.5 GetSuperBase ( envRec )

抽象操作GetSuperBase接受参数envRec(一个函数环境记录)并返回对象、nullundefined。它返回作为envRec中绑定的super属性访问基础的对象。值undefined表示这种访问将产生运行时错误。调用时执行以下步骤:

  1. homeenvRec.[[FunctionObject]].[[HomeObject]]
  2. 如果homeundefined,返回undefined
  3. 断言home是一个普通对象
  4. 返回! home.[[GetPrototypeOf]]()。

9.1.1.4 全局环境记录

全局环境记录用于表示被在共同领域中处理的所有ECMAScript 脚本元素所共享的最外层作用域。全局环境记录为内置全局变量(第19章)、全局对象的属性以及在脚本中出现的所有顶级声明(8.2.98.2.11)提供绑定。

全局环境记录在逻辑上是单个记录,但它被指定为一个封装对象环境记录声明式环境记录的复合体。对象环境记录以关联领域记录全局对象为基础对象。这个全局对象是全局环境记录的GetThisBinding具体方法返回的值。全局环境记录的对象环境记录组件包含所有内置全局变量的绑定(第19章)以及由全局代码中的函数声明生成器声明异步函数声明异步生成器声明变量语句引入的所有绑定。全局代码中所有其他ECMAScript声明的绑定包含在全局环境记录的声明式环境记录组件中。

属性可以直接在全局对象上创建。因此,全局环境记录的对象环境记录组件可能包含由函数声明生成器声明异步函数声明异步生成器声明变量声明声明显式创建的绑定和作为全局对象属性隐式创建的绑定。为了识别哪些绑定是使用声明显式创建的,全局环境记录维护一个使用CreateGlobalVarBindingCreateGlobalFunctionBinding抽象操作绑定的名称列表。

全局环境记录具有表20中列出的附加字段和表21中列出的附加方法。

表20:全局环境记录的附加字段
字段名称 含义
[[ObjectRecord]] 一个对象环境记录 绑定对象是全局对象。它包含全局内置绑定以及关联领域的全局代码中的函数声明生成器声明异步函数声明异步生成器声明变量声明绑定。
[[GlobalThisValue]] 一个对象 在全局作用域中this返回的值。宿主可以提供任何ECMAScript对象值。
[[DeclarativeRecord]] 一个声明式环境记录 包含关联领域代码的全局代码中除函数声明生成器声明异步函数声明异步生成器声明变量声明绑定外的所有声明的绑定。
表21:全局环境记录的附加方法
方法 目的
GetThisBinding() 返回此环境记录this绑定的值。

9.1.1.4.1 HasBinding ( N )

全局环境记录 envRec的HasBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它确定参数标识符是否是记录绑定的标识符之一。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 返回true
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.HasBinding(N)。

9.1.1.4.2 CreateMutableBinding ( N, D )

全局环境记录 envRec的CreateMutableBinding具体方法接受参数N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它为名称N创建一个新的未初始化的可变绑定。绑定在关联的声明式记录中创建。声明式记录中不得已存在N的绑定。如果Dtrue,则新绑定被标记为可删除的。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 抛出TypeError异常。
  3. 返回! DclRec.CreateMutableBinding(N, D)。

9.1.1.4.3 CreateImmutableBinding ( N, S )

全局环境记录 envRec的CreateImmutableBinding具体方法接受参数N(字符串)和S(布尔值) 并返回包含 unused正常完成抛出完成。它为名称N创建一个新的未初始化的不可变绑定。此环境记录中不得已存在N的绑定。如果Strue,则新绑定被标记为严格绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 抛出TypeError异常。
  3. 返回! DclRec.CreateImmutableBinding(N, S)。

9.1.1.4.4 InitializeBinding ( N, V )

全局环境记录 envRec的InitializeBinding具体方法接受参数N(字符串)和VECMAScript语言值) 并返回包含 unused正常完成抛出完成。它用于将名称为N的标识符的当前绑定的绑定值设置为值VN的未初始化绑定必须已经存在。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回! DclRec.InitializeBinding(N, V)。
  3. 断言: 如果绑定存在,它必须在对象环境记录中。
  4. ObjRecenvRec.[[ObjectRecord]]
  5. 返回? ObjRec.InitializeBinding(N, V)。

9.1.1.4.5 SetMutableBinding ( N, V, S )

全局环境记录 envRec的SetMutableBinding具体方法接受参数N(字符串)、VECMAScript语言值) 和S(布尔值)并返回包含 unused正常完成抛出完成。它尝试将名称为N的标识符的当前绑定的绑定值更改为值V。如果绑定是不可变绑定且Strue,则抛出TypeError。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回? DclRec.SetMutableBinding(N, V, S)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.SetMutableBinding(N, V, S)。

9.1.1.4.6 GetBindingValue ( N, S )

全局环境记录 envRec的GetBindingValue具体方法接受参数N(字符串) 和S(布尔值)并返回包含ECMAScript语言值正常完成抛出完成。它返回名称为N的绑定标识符的值。如果绑定是未初始化绑定,则抛出ReferenceError异常。名称为N的属性通常已经存在,但如果不存在或当前不可写,错误处理由S确定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回? DclRec.GetBindingValue(N, S)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. 返回? ObjRec.GetBindingValue(N, S)。

9.1.1.4.7 DeleteBinding ( N )

全局环境记录 envRec的DeleteBinding具体方法接受参数N(字符串) 并返回包含布尔值的正常完成抛出完成。它只能删除已明确指定为可删除的绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 如果! DclRec.HasBinding(N)是true, 则
    1. 返回! DclRec.DeleteBinding(N)。
  3. ObjRecenvRec.[[ObjectRecord]]
  4. globalObjectObjRec.[[BindingObject]]
  5. existingProp为? HasOwnProperty(globalObject, N)。
  6. 如果existingProptrue,则
    1. 返回? ObjRec.DeleteBinding(N)。
  7. 返回true

9.1.1.4.8 HasThisBinding ( )

全局环境记录 envRec的HasThisBinding具体方法不接受参数并返回true。调用时执行以下步骤:

  1. 返回true

全局环境记录总是提供this绑定。

9.1.1.4.9 HasSuperBinding ( )

全局环境记录 envRec的HasSuperBinding具体方法不接受参数并返回false。调用时执行以下步骤:

  1. 返回false

全局环境记录不提供super绑定。

9.1.1.4.10 WithBaseObject ( )

全局环境记录 envRec的WithBaseObject具体方法不接受参数并返回undefined。调用时执行以下步骤:

  1. 返回undefined

9.1.1.4.11 GetThisBinding ( )

全局环境记录 envRec的GetThisBinding具体方法不接受参数并返回包含对象的正常完成。调用时执行以下步骤:

  1. 返回envRec.[[GlobalThisValue]]

9.1.1.4.12 HasLexicalDeclaration ( envRec, N )

抽象操作HasLexicalDeclaration接受参数envRec(一个全局环境记录) 和N(字符串)并返回布尔值。它确定参数标识符是否在envRec中有使用词法声明如词法声明类声明创建的绑定。调用时执行以下步骤:

  1. DclRecenvRec.[[DeclarativeRecord]]
  2. 返回! DclRec.HasBinding(N)。

9.1.1.4.13 HasRestrictedGlobalProperty ( envRec, N )

抽象操作HasRestrictedGlobalProperty接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定参数标识符是否是全局对象的属性名称,该属性不得被全局词法绑定遮蔽。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefined,返回false
  5. 如果existingProp.[[Configurable]]true,返回false
  6. 返回true

属性可能存在于全局对象上,这些属性是直接创建的而不是使用var或函数声明声明的。不能创建与全局对象的不可配置属性同名的全局词法绑定。全局属性"undefined"就是这样一个属性的例子。

9.1.1.4.14 CanDeclareGlobalVar ( envRec, N )

抽象操作CanDeclareGlobalVar接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定如果为相同参数N调用相应的CreateGlobalVarBinding调用是否会成功。允许冗余的var声明和对预先存在的全局对象属性的var声明。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. hasProperty为? HasOwnProperty(globalObject, N)。
  4. 如果hasPropertytrue,返回true
  5. 返回? IsExtensible(globalObject)。

9.1.1.4.15 CanDeclareGlobalFunction ( envRec, N )

抽象操作CanDeclareGlobalFunction接受参数envRec(一个全局环境记录) 和N(字符串)并返回包含布尔值的正常完成抛出完成。它确定如果为相同参数N调用相应的CreateGlobalFunctionBinding调用是否会成功。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefined,返回? IsExtensible(globalObject)。
  5. 如果existingProp.[[Configurable]]true,返回true
  6. 如果IsDataDescriptor(existingProp) 是trueexistingProp有属性值{ [[Writable]]: true, [[Enumerable]]: true },返回true
  7. 返回false

9.1.1.4.16 CreateGlobalVarBinding ( envRec, N, D )

抽象操作CreateGlobalVarBinding接受参数envRec(一个全局环境记录)、N(字符串)和D(布尔值) 并返回包含 unused正常完成抛出完成。它在关联的对象环境记录中创建并初始化可变绑定。如果绑定已经存在,则重用它并假定已初始化。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. hasProperty为? HasOwnProperty(globalObject, N)。
  4. extensible为? IsExtensible(globalObject)。
  5. 如果hasPropertyfalseextensibletrue,则
    1. 执行? ObjRec.CreateMutableBinding(N, D)。
    2. 执行? ObjRec.InitializeBinding(N, undefined)。
  6. 返回unused

9.1.1.4.17 CreateGlobalFunctionBinding ( envRec, N, V, D )

抽象操作CreateGlobalFunctionBinding接受参数envRec(一个全局环境记录)、N(字符串)、VECMAScript语言值) 和D(布尔值)并返回包含 unused正常完成抛出完成。它在关联的对象环境记录中创建并初始化可变绑定。如果绑定已经存在,则替换它。调用时执行以下步骤:

  1. ObjRecenvRec.[[ObjectRecord]]
  2. globalObjectObjRec.[[BindingObject]]
  3. existingProp为? globalObject.[[GetOwnProperty]](N)。
  4. 如果existingPropundefinedexistingProp.[[Configurable]]true,则
    1. desc为属性描述符{ [[Value]]: V, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: D }。
  5. 否则,
    1. desc为属性描述符{ [[Value]]: V }。
  6. 执行? DefinePropertyOrThrow(globalObject, N, desc)。
  7. 执行? Set(globalObject, N, V, false)。
  8. 返回unused

全局函数声明总是表示为全局对象的自有属性。如果可能,现有的自有属性会被重新配置为具有标准的属性值集合。步骤7等效于调用InitializeBinding具体方法所做的操作,如果globalObject是代理,将产生相同的代理陷阱调用序列。

9.1.1.5 模块环境记录

模块环境记录是一个 声明式环境记录,用于表示 ECMAScript 模块的外部作用域。除了普通的可变和不可变绑定之外,模块环境记录还提供不可变的导入绑定,这些绑定提供对存在于另一个 环境记录中的目标绑定的间接访问。

模块环境记录支持 声明式环境记录表 16 中列出的所有方法,除了 GetBindingValue、DeleteBinding、HasThisBinding 和 GetThisBinding 之外,所有这些方法都共享相同的规范。此外,模块环境记录支持 表 22 中列出的方法:

表 22:模块环境记录的附加方法
方法 目的
GetThisBinding() 返回此 环境记录this 绑定的值。

9.1.1.5.1 GetBindingValue ( N, S )

模块环境记录 envRec 的 GetBindingValue 具体方法接收参数 N(一个字符串)和 S(一个布尔值),并返回 包含 ECMAScript 语言值的正常完成或 抛出完成。它返回名称为 N 的绑定标识符的值。但是,如果绑定是间接绑定,则返回目标绑定的值。如果绑定存在但未初始化,则抛出 ReferenceError。调用时执行以下步骤:

  1. 断言Strue
  2. 断言envRec 有一个 N 的绑定。
  3. 如果 N 的绑定是间接绑定,那么
    1. MN2 为创建此 N 绑定时提供的间接值。
    2. targetEnvM.[[Environment]]
    3. 如果 targetEnvempty,抛出 ReferenceError 异常。
    4. 返回 ? targetEnv.GetBindingValue(N2, true)。
  4. 如果 envRecN 的绑定是未初始化的绑定,抛出 ReferenceError 异常。
  5. 返回 envRec 中当前绑定到 N 的值。

S 将始终为 true,因为 模块始终是 严格模式代码

9.1.1.5.2 DeleteBinding ( N )

模块环境记录的 DeleteBinding 具体方法在本规范中从未使用。

模块环境记录仅在严格代码中使用,并且早期错误规则防止在严格代码中将 delete 操作符应用于会解析为 模块环境记录绑定的 引用记录。参见 13.5.1.1

9.1.1.5.3 HasThisBinding ( )

模块环境记录 envRec 的 HasThisBinding 具体方法不接收参数,返回 true。调用时执行以下步骤:

  1. 返回 true

模块环境记录始终提供 this 绑定。

9.1.1.5.4 GetThisBinding ( )

模块环境记录 envRec 的 GetThisBinding 具体方法不接收参数,返回 包含 undefined 的正常完成。调用时执行以下步骤:

  1. 返回 undefined

9.1.1.5.5 CreateImportBinding ( envRec, N, M, N2 )

抽象操作 CreateImportBinding 接收参数 envRec(一个 模块环境记录)、N(一个字符串)、M(一个 模块记录)和 N2(一个字符串),并返回 unused。它为名称 N 创建一个新的已初始化的不可变间接绑定。envRec 中不能已经存在 N 的绑定。N2 是存在于 M模块环境记录中的绑定的名称。对新绑定值的访问将间接访问目标绑定的绑定值。调用时执行以下步骤:

  1. 断言envRec 还没有 N 的绑定。
  2. 断言: 当 M.[[Environment]] 被实例化时,它将有一个 N2 的直接绑定。
  3. envRec 中为 N 创建一个不可变的间接绑定,该绑定引用 MN2 作为其目标绑定,并记录该绑定已初始化。
  4. 返回 unused

9.1.2 环境记录操作

本规范中使用以下抽象操作来操作环境记录

9.1.2.1 GetIdentifierReference ( env, name, strict )

抽象操作 GetIdentifierReference 接收参数 env(一个环境记录null)、name(一个字符串)和 strict(一个布尔值),并返回包含引用记录的正常完成或抛出完成。调用时执行以下步骤:

  1. 如果 envnull,那么
    1. 返回引用记录 { [[Base]]: unresolvable, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  2. exists 为 ? env.HasBinding(name)。
  3. 如果 existstrue,那么
    1. 返回引用记录 { [[Base]]: env, [[ReferencedName]]: name, [[Strict]]: strict, [[ThisValue]]: empty }。
  4. 否则,
    1. outerenv.[[OuterEnv]]
    2. 返回 ? GetIdentifierReference(outer, name, strict)。

9.1.2.2 NewDeclarativeEnvironment ( E )

抽象操作 NewDeclarativeEnvironment 接收参数 E(一个环境记录null),并返回一个声明式环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新声明式环境记录
  2. 设置 env.[[OuterEnv]]E
  3. 返回 env

9.1.2.3 NewObjectEnvironment ( O, W, E )

抽象操作 NewObjectEnvironment 接收参数 O(一个对象)、W(一个布尔值)和 E(一个环境记录null),并返回一个对象环境记录。调用时执行以下步骤:

  1. env 为一个新的对象环境记录
  2. 设置 env.[[BindingObject]]O
  3. 设置 env.[[IsWithEnvironment]]W
  4. 设置 env.[[OuterEnv]]E
  5. 返回 env

9.1.2.4 NewFunctionEnvironment ( F, newTarget )

抽象操作 NewFunctionEnvironment 接收参数 F(一个 ECMAScript 函数对象)和 newTarget(一个对象或 undefined),并返回一个函数环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新函数环境记录
  2. 设置 env.[[FunctionObject]]F
  3. 如果 F.[[ThisMode]]lexical,设置 env.[[ThisBindingStatus]]lexical
  4. 否则,设置 env.[[ThisBindingStatus]]uninitialized
  5. 设置 env.[[NewTarget]]newTarget
  6. 设置 env.[[OuterEnv]]F.[[Environment]]
  7. 返回 env

9.1.2.5 NewGlobalEnvironment ( G, thisValue )

抽象操作 NewGlobalEnvironment 接收参数 G(一个对象)和 thisValue(一个对象),并返回一个全局环境记录。调用时执行以下步骤:

  1. objRecNewObjectEnvironment(G, false, null)。
  2. dclRecNewDeclarativeEnvironment(null)。
  3. env 为一个新的全局环境记录
  4. 设置 env.[[ObjectRecord]]objRec
  5. 设置 env.[[GlobalThisValue]]thisValue
  6. 设置 env.[[DeclarativeRecord]]dclRec
  7. 设置 env.[[OuterEnv]]null
  8. 返回 env

9.1.2.6 NewModuleEnvironment ( E )

抽象操作 NewModuleEnvironment 接收参数 E(一个环境记录),并返回一个模块环境记录。调用时执行以下步骤:

  1. env 为一个不包含绑定的新模块环境记录
  2. 设置 env.[[OuterEnv]]E
  3. 返回 env

9.2 私有环境记录

私有环境记录是一种规范机制,用于基于 ECMAScript 代码中 类声明类表达式的词法嵌套结构来跟踪私有名称。它们类似于但区别于环境记录。每个私有环境记录都与一个 类声明类表达式关联。每次求值这样的类时,都会创建一个新的私有环境记录来记录该类声明的私有名称

每个私有环境记录都具有表 23中定义的字段。

表 23:私有环境记录字段
字段名称 值类型 含义
[[OuterPrivateEnvironment]] 一个私有环境记录null 最近的包含类的私有环境记录。如果与此私有环境记录关联的类不包含在任何其他类中,则为 null
[[Names]] 私有名称列表 此类声明的私有名称

9.2.1 私有环境记录操作

本规范中使用以下抽象操作来操作私有环境记录

9.2.1.1 NewPrivateEnvironment ( outerPrivateEnv )

抽象操作 NewPrivateEnvironment 接收参数 outerPrivateEnv(一个私有环境记录null),并返回一个私有环境记录。调用时执行以下步骤:

  1. names 为一个新的空列表
  2. 返回私有环境记录 { [[OuterPrivateEnvironment]]: outerPrivateEnv, [[Names]]: names }。

9.2.1.2 ResolvePrivateIdentifier ( privateEnv, identifier )

抽象操作 ResolvePrivateIdentifier 接收参数 privateEnv(一个私有环境记录)和 identifier(一个字符串),并返回一个私有名称。调用时执行以下步骤:

  1. namesprivateEnv.[[Names]]
  2. 对于 names 的每个私有名称 pn,执行
    1. 如果 pn.[[Description]]identifier,那么
      1. 返回 pn
  3. outerPrivateEnvprivateEnv.[[OuterPrivateEnvironment]]
  4. 断言outerPrivateEnv 不是 null
  5. 返回 ResolvePrivateIdentifier(outerPrivateEnv, identifier)。

9.3 领域

在求值之前,所有 ECMAScript 代码都必须与一个领域关联。从概念上讲,一个领域由一组内建对象、一个 ECMAScript 全局环境、在该全局环境作用域内加载的所有 ECMAScript 代码以及其他关联的状态和资源组成。

在本规范中,领域表示为具有表 24中指定字段的领域记录

表 24:领域记录字段
字段名称 含义
[[AgentSignifier]] 一个代理标识符 拥有此领域代理
[[Intrinsics]] 一个记录,其字段名称是内建键,其值是对象 与此领域关联的代码使用的内建值
[[GlobalObject]] 一个对象 领域全局对象
[[GlobalEnv]] 一个全局环境记录 领域的全局环境
[[TemplateMap]] 具有字段 [[Site]](一个模板字面量解析节点)和 [[Array]](一个数组)的记录列表

模板对象使用其领域记录[[TemplateMap]] 为每个领域单独规范化。每个 [[Site]] 值是一个解析节点,是一个模板字面量。关联的 [[Array]] 值是传递给标签函数的相应模板对象。

注 1
一旦解析节点变得不可达,相应的 [[Array]] 也变得不可达,如果实现从 [[TemplateMap]] 列表中移除该对,这是不可观察的。
[[LoadedModules]] 已加载模块请求记录列表

从此领域导入的说明符字符串到已解析模块记录的映射。列表不包含两个不同的记录 r1r2,使得 ModuleRequestsEqual(r1, r2) 为 true

注 2
HostLoadImportedModule16.2.1.10 注 1)中所述,领域记录中的 [[LoadedModules]] 仅在没有活动脚本或模块的上下文中运行 import() 表达式时使用。
[[HostDefined]] 任何值(默认值为 undefined 为需要将附加信息与领域记录关联的宿主保留的字段。

9.3.1 InitializeHostDefinedRealm ( )

抽象操作 InitializeHostDefinedRealm 不接收参数,并返回包含 unused 的正常完成或抛出完成。调用时执行以下步骤:

  1. realm 为一个新的领域记录
  2. 执行 CreateIntrinsics(realm)。
  3. 设置 realm.[[AgentSignifier]]AgentSignifier()。
  4. 设置 realm.[[TemplateMap]] 为一个新的空列表
  5. newContext 为一个新的执行上下文
  6. 设置 newContext 的 Function 为 null
  7. 设置 newContext领域realm
  8. 设置 newContext 的 ScriptOrModule 为 null
  9. newContext 推入执行上下文栈newContext 现在是运行执行上下文
  10. 如果宿主要求使用异质对象作为 realm全局对象,那么
    1. global 为以宿主定义的方式创建的这样一个对象。
  11. 否则,
    1. globalOrdinaryObjectCreate(realm.[[Intrinsics]].[[%Object.prototype%]])。
  12. 如果宿主要求 realm 的全局作用域中的 this 绑定返回除全局对象之外的对象,那么
    1. thisValue 为以宿主定义的方式创建的这样一个对象。
  13. 否则,
    1. thisValueglobal
  14. 设置 realm.[[GlobalObject]]global
  15. 设置 realm.[[GlobalEnv]]NewGlobalEnvironment(global, thisValue)。
  16. 执行 ? SetDefaultGlobalBindings(realm)。
  17. global 上创建任何宿主定义全局对象属性。
  18. 返回 unused

9.3.2 CreateIntrinsics ( realmRec )

抽象操作 CreateIntrinsics 接收参数 realmRec(一个领域记录),并返回 unused。调用时执行以下步骤:

  1. 设置 realmRec.[[Intrinsics]] 为一个新的记录
  2. 使用表 6中列出的值设置 realmRec.[[Intrinsics]] 的字段。字段名称是表第一列中列出的名称。每个字段的值是一个新的对象值,完全且递归地填充了属性值,如子句1928中每个对象的规范所定义。所有对象属性值都是新创建的对象值。所有作为内建函数对象的值都通过执行 CreateBuiltinFunction(steps, length, name, slots, realmRec, prototype) 创建,其中 steps 是本规范提供的该函数的定义,name 是函数 "name" 属性的初始值,length 是函数 "length" 属性的初始值,slots 是函数指定的内部插槽名称的列表(如果有),prototype 是函数 [[Prototype]] 内部插槽的指定值。内建对象及其属性的创建必须有序,以避免依赖尚未创建的对象。
  3. 执行 AddRestrictedFunctionProperties(realmRec.[[Intrinsics]].[[%Function.prototype%]], realmRec)。
  4. 返回 unused

9.3.3 SetDefaultGlobalBindings ( realmRec )

抽象操作 SetDefaultGlobalBindings 接收参数 realmRec(一个领域记录),并返回包含 unused 的正常完成或抛出完成。调用时执行以下步骤:

  1. globalrealmRec.[[GlobalObject]]
  2. 对于子句19中指定的全局对象的每个属性,执行
    1. name属性名称的字符串值。
    2. desc 为该属性的完全填充的数据属性描述符,包含该属性的指定特性。对于19.219.319.4中列出的属性,[[Value]] 特性的值是来自 realmRec 的相应内建对象。
    3. 执行 ? DefinePropertyOrThrow(global, name, desc)。
  3. 返回 unused

9.4 执行上下文

执行上下文是一种规范设备,用于跟踪 ECMAScript 实现对代码的运行时求值。在任何时候,每个代理最多有一个实际在执行代码的执行上下文。这被称为代理运行执行上下文。本规范中对运行执行上下文的所有引用都指周围代理运行执行上下文

执行上下文栈用于跟踪执行上下文。运行执行上下文始终是该栈的顶部元素。每当控制从与当前运行执行上下文关联的可执行代码转移到与该执行上下文不关联的可执行代码时,就会创建一个新的执行上下文。新创建的执行上下文被推入栈中并成为运行执行上下文

执行上下文包含跟踪其关联代码的执行进度所需的任何实现特定状态。每个执行上下文至少具有表 25中列出的状态组件。

表 25:所有执行上下文的状态组件
组件 目的
代码求值状态 执行、暂停和恢复与此执行上下文关联的代码求值所需的任何状态。
Function 如果此执行上下文正在求值函数对象的代码,则此组件的值为该函数对象。如果上下文正在求值脚本模块的代码,则值为 null
领域 关联代码访问 ECMAScript 资源的领域记录
ScriptOrModule 关联代码起源的模块记录脚本记录。如果没有起源脚本或模块,如在InitializeHostDefinedRealm中创建的原始执行上下文的情况,则值为 null

运行执行上下文对代码的求值可能在本规范内定义的各个点被暂停。一旦运行执行上下文被暂停,不同的执行上下文可能成为运行执行上下文并开始求值其代码。在稍后的某个时间,被暂停的执行上下文可能再次成为运行执行上下文并在之前被暂停的点继续求值其代码。运行执行上下文状态在执行上下文间的转换通常以类似栈的后进先出方式发生。然而,某些 ECMAScript 特性需要运行执行上下文的非 LIFO 转换。

运行执行上下文领域组件的值也被称为当前领域记录运行执行上下文的 Function 组件的值也被称为活动函数对象

ECMAScript 代码执行上下文具有表 26中列出的附加状态组件。

表 26:ECMAScript 代码执行上下文的附加状态组件
组件 目的
LexicalEnvironment 标识用于解析此执行上下文内代码进行的标识符引用的环境记录
VariableEnvironment 标识保存此执行上下文变量语句创建的绑定的环境记录
PrivateEnvironment 标识保存最近的包含类中类元素创建的私有名称私有环境记录。如果没有包含类,则为 null

执行上下文的 LexicalEnvironment 和 VariableEnvironment 组件始终是环境记录

表示生成器求值的执行上下文具有表 27中列出的附加状态组件。

表 27:生成器执行上下文的附加状态组件
组件 目的
Generator 执行上下文正在求值的生成器。

在大多数情况下,只有运行执行上下文执行上下文栈的顶部)被本规范内的算法直接操作。因此,当使用术语"LexicalEnvironment"和"VariableEnvironment"而不加限定时,它们指的是运行执行上下文的这些组件。

执行上下文纯粹是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。ECMAScript 代码不可能直接访问或观察执行上下文。

9.4.1 GetActiveScriptOrModule ( )

抽象操作 GetActiveScriptOrModule 不接收参数,并返回脚本记录模块记录null。它用于基于运行执行上下文确定运行的脚本或模块。调用时执行以下步骤:

  1. 如果执行上下文栈为空,返回 null
  2. ec执行上下文栈上 ScriptOrModule 组件不为 null 的最顶层执行上下文
  3. 如果不存在这样的执行上下文,返回 null。否则,返回 ec 的 ScriptOrModule。

9.4.2 ResolveBinding ( name [ , env ] )

抽象操作 ResolveBinding 接收参数 name(一个字符串)和可选参数 env(一个环境记录undefined),并返回包含引用记录的正常完成或抛出完成。它用于确定 name 的绑定。env 可用于显式提供要搜索绑定的环境记录。调用时执行以下步骤:

  1. 如果 env 不存在或 envundefined,那么
    1. 设置 env运行执行上下文的 LexicalEnvironment。
  2. 断言env 是一个环境记录
  3. strictIsStrict(正在求值的语法产生式)。
  4. 返回 ? GetIdentifierReference(env, name, strict)。

ResolveBinding 的结果始终是一个引用记录,其 [[ReferencedName]] 字段为 name

9.4.3 GetThisEnvironment ( )

抽象操作 GetThisEnvironment 不接收参数,并返回一个环境记录。它找到当前提供关键字 this 绑定的环境记录。调用时执行以下步骤:

  1. env运行执行上下文的 LexicalEnvironment。
  2. 重复,
    1. existsenv.HasThisBinding()。
    2. 如果 existstrue,返回 env
    3. outerenv.[[OuterEnv]]
    4. 断言outer 不是 null
    5. 设置 envouter

步骤2中的循环将始终终止,因为环境列表总是以具有 this 绑定的全局环境结束。

9.4.5 ResolveThisBinding ( )

抽象操作 ResolveThisBinding 不接收参数,并返回包含ECMAScript 语言值的正常完成或抛出完成。它使用运行执行上下文的 LexicalEnvironment 确定关键字 this 的绑定。调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 返回 ? envRec.GetThisBinding()。

9.4.5 GetNewTarget ( )

抽象操作 GetNewTarget 不接收参数,并返回一个对象或 undefined。它使用运行执行上下文的 LexicalEnvironment 确定 NewTarget 值。调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 断言envRec 有一个 [[NewTarget]] 字段。
  3. 返回 envRec.[[NewTarget]]

9.4.6 GetGlobalObject ( )

抽象操作 GetGlobalObject 不接收参数,并返回一个对象。它返回当前运行执行上下文使用的全局对象。调用时执行以下步骤:

  1. currentRealm当前领域记录
  2. 返回 currentRealm.[[GlobalObject]]

9.5 作业和宿主操作入队作业

作业是一个无参数的抽象闭包,当没有其他 ECMAScript 计算正在进行时,它启动 ECMAScript 计算。

作业由特定代理中的 ECMAScript 宿主环境调度执行。本规范描述了宿主钩子 HostEnqueueGenericJobHostEnqueueFinalizationRegistryCleanupJobHostEnqueuePromiseJobHostEnqueueTimeoutJob来调度作业。本规范中的宿主钩子按对作业调度施加的附加约束进行组织。宿主可以定义调度作业的附加抽象操作。这些操作接受作业抽象闭包领域(一个领域记录null)作为参数。如果提供了领域记录,这些操作调度作业在将来某个时间在提供的领域中执行,在拥有该领域代理中。如果为领域提供null,则作业不会求值 ECMAScript 代码。它们的实现必须符合以下要求:

注 1
宿主环境不需要在调度方面统一对待作业。例如,Web 浏览器和 Node.js 将 Promise 处理作业视为比其他工作更高的优先级;未来的特性可能添加不被视为如此高优先级的作业

在任何特定时间,scriptOrModule(一个脚本记录、一个模块记录null)是活动脚本或模块,如果所有以下条件都为真:

在任何特定时间,如果所有以下条件都为真,则执行准备求值 ECMAScript 代码

注 2

宿主环境可以通过将执行上下文推入执行上下文栈来准备执行求值代码。具体步骤是实现定义的。

领域的具体选择取决于宿主环境。这个初始执行上下文领域仅在调用任何回调函数之前使用。当调用与作业相关的回调函数(如 Promise 处理程序)时,调用会推入自己的执行上下文领域

特定类型的作业有附加的一致性要求。

9.5.1 作业回调记录

作业回调记录是用于存储函数对象宿主定义值的记录值。通过宿主入队的作业调用的函数对象可能有附加的宿主定义上下文。为了传播状态,作业抽象闭包不应该直接捕获和调用函数对象。相反,使用HostMakeJobCallbackHostCallJobCallback

例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用宿主定义值来为 Promise 回调传播现任设置对象。

作业回调记录具有表 28中列出的字段。

表 28:作业回调记录字段
字段名称 含义
[[Callback]] 一个函数对象 调用作业时要调用的函数。
[[HostDefined]] 任何值(默认值为empty 宿主保留使用的字段。

9.5.2 HostMakeJobCallback ( callback )

宿主定义的抽象操作 HostMakeJobCallback 接收参数 callback(一个函数对象),并返回一个作业回调记录

HostMakeJobCallback 的实现必须符合以下要求:

HostMakeJobCallback 的默认实现在调用时执行以下步骤:

  1. 返回作业回调记录 { [[Callback]]: callback, [[HostDefined]]: empty }。

非 Web 浏览器的 ECMAScript 宿主必须使用 HostMakeJobCallback 的默认实现。

这在回调被传递给负责其最终调度和运行的函数时调用。例如,promise.then(thenAction) 在调用 Promise.prototype.then 时对 thenAction 调用 MakeJobCallback,而不是在调度反应作业时。

9.5.3 HostCallJobCallback ( jobCallback, V, argumentsList )

宿主定义的抽象操作 HostCallJobCallback 接收参数 jobCallback(一个作业回调记录)、V(一个ECMAScript 语言值)和 argumentsListECMAScript 语言值列表),并返回包含ECMAScript 语言值的正常完成或抛出完成

HostCallJobCallback 的实现必须符合以下要求:

  • 它必须执行并返回Call(jobCallback.[[Callback]], V, argumentsList)的结果。

这个要求意味着宿主不能改变本规范中定义的函数对象[[Call]]行为。

HostCallJobCallback 的默认实现在调用时执行以下步骤:

  1. 断言IsCallable(jobCallback.[[Callback]]) 是true
  2. 返回 ? Call(jobCallback.[[Callback]], V, argumentsList)。

非 Web 浏览器的 ECMAScript 宿主必须使用 HostCallJobCallback 的默认实现。

9.5.4 HostEnqueueGenericJob ( job, realm )

宿主定义的抽象操作 HostEnqueueGenericJob 接收参数 job(一个作业抽象闭包)和realm(一个领域记录),并返回unused。它在由realm.[[AgentSignifier]]表示的代理中的领域 realm 中调度job在将来某个时间执行。与此算法一起使用的抽象闭包旨在无附加约束(如优先级和排序)地调度。

HostEnqueueGenericJob 的实现必须符合9.5中的要求。

9.5.5 HostEnqueuePromiseJob ( job, realm )

宿主定义的抽象操作 HostEnqueuePromiseJob 接收参数 job(一个作业抽象闭包)和realm(一个领域记录null),并返回unused。它调度job在将来某个时间执行。与此算法一起使用的抽象闭包旨在与 Promise 处理相关,或者以与 Promise 处理操作相等的优先级调度。

HostEnqueuePromiseJob 的实现必须符合9.5中的要求以及以下要求:

NewPromiseResolveThenableJob返回的作业realm通常是在then函数对象上调用GetFunctionRealm的结果。NewPromiseReactionJob返回的作业realm通常是在处理程序不是undefined时在处理程序上调用GetFunctionRealm的结果。如果处理程序是undefined,则realmnull。对于两种类型的作业,当GetFunctionRealm异常完成(即在被撤销的代理上调用)时,realmGetFunctionRealm调用时的当前领域记录。当realmnull时,不会求值用户 ECMAScript 代码,也不会创建新的 ECMAScript 对象(例如错误对象)。例如,WHATWG HTML 规范(https://html.spec.whatwg.org/)使用realm来检查运行脚本的能力和入口概念。

9.5.6 HostEnqueueTimeoutJob ( timeoutJob, realm, milliseconds )

宿主定义的抽象操作 HostEnqueueTimeoutJob 接收参数 timeoutJob(一个作业抽象闭包)、realm(一个领域记录)和milliseconds(一个非负有限数字),并返回unused。它在由realm.[[AgentSignifier]]表示的代理中的领域 realm 中调度timeoutJob在至少milliseconds毫秒后执行。

HostEnqueueTimeoutJob 的实现必须符合9.5中的要求。

9.6 代理

代理包含一组 ECMAScript 执行上下文、一个执行上下文栈、一个运行执行上下文、一个代理记录和一个执行线程。除了执行线程之外,代理的组成部分专属于该代理

代理执行线程在该代理执行上下文上独立于其他代理执行算法步骤,但是一个执行线程可以被多个代理用作执行线程,只要共享该线程的代理都没有[[CanBlock]]字段为true代理记录

注 1

例如,一些 Web 浏览器在浏览器窗口的多个不相关选项卡之间共享单个执行线程

代理执行线程正在执行算法步骤时,该代理是那些步骤的周围代理。这些步骤使用周围代理来访问在该代理内持有的规范级执行对象:运行执行上下文执行上下文栈代理记录的字段。

代理标识符是用于标识代理的全局唯一不透明值。

表 29:代理记录字段
字段名称 含义
[[LittleEndian]] 布尔值 当算法GetValueFromBufferSetValueInBuffer需要时为isLittleEndian参数计算的默认值。选择是实现定义的,应该是对实现最有效的选择。一旦该值被观察到,它就不能改变。
[[CanBlock]] 布尔值 确定代理是否可以阻塞。
[[Signifier]] 一个代理标识符 在其代理集群内唯一标识代理
[[IsLockFree1]] 布尔值 如果对单字节值的原子操作是无锁的,则为true,否则为false
[[IsLockFree2]] 布尔值 如果对双字节值的原子操作是无锁的,则为true,否则为false
[[IsLockFree8]] 布尔值 如果对八字节值的原子操作是无锁的,则为true,否则为false
[[CandidateExecution]] 一个候选执行记录 参见内存模型
[[KeptAlive]] 对象或符号的列表 初始为一个新的空列表,表示要保持活跃直到当前作业结束的对象和/或符号列表。
[[ModuleAsyncEvaluationCount]] 一个整数 初始为 0,用于为异步或具有异步依赖的模块的[[AsyncEvaluationOrder]]字段分配唯一的递增值。

一旦[[Signifier]][[IsLockFree1]][[IsLockFree2]]的值被代理集群中的任何代理观察到,它们就不能改变。

注 2

[[IsLockFree1]][[IsLockFree2]]的值不一定由硬件决定,也可能反映可能随时间和 ECMAScript 实现而变化的实现选择。

没有[[IsLockFree4]]字段:4 字节原子操作总是无锁的。

实际上,如果原子操作是用任何类型的锁实现的,则该操作不是无锁的。无锁并不意味着无等待:对于完成无锁原子操作可能需要多少个机器步骤没有上限。

大小为n的原子访问是无锁的,并不意味着大小为n的非原子访问的(感知的)原子性,具体来说,非原子访问仍然可能作为几个单独的内存访问序列来执行。详见ReadSharedMemoryWriteSharedMemory

注 3

代理是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。

9.6.1 AgentSignifier ( )

抽象操作 AgentSignifier 不接收参数,并返回一个代理标识符。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. 返回AR.[[Signifier]]

9.6.2 AgentCanSuspend ( )

抽象操作 AgentCanSuspend 不接收参数,并返回一个布尔值。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. 返回AR.[[CanBlock]]

在某些环境中,给定代理暂停可能不合理。例如,在 Web 浏览器环境中,禁止暂停文档的主事件处理线程可能是合理的,而仍然允许工作线程的事件处理线程暂停。

9.6.3 IncrementModuleAsyncEvaluationCount ( )

抽象操作 IncrementModuleAsyncEvaluationCount 不接收参数,并返回一个整数。调用时执行以下步骤:

  1. AR周围代理代理记录
  2. countAR.[[ModuleAsyncEvaluationCount]]
  3. 设置AR.[[ModuleAsyncEvaluationCount]]count + 1。
  4. 返回count

此值仅用于跟踪挂起模块之间的相对求值顺序。当没有挂起模块时,实现可以不可观察地将[[ModuleAsyncEvaluationCount]]重置为 0。

9.7 代理集群

代理集群是可以通过操作共享内存进行通信的代理的最大集合。

注 1

不同代理内的程序可以通过未指定的方式共享内存。至少,SharedArrayBuffers 的后备内存可以在集群中的代理之间共享。

可能存在可以通过消息传递进行通信但不能共享内存的代理;它们永远不在同一个代理集群中。

每个代理都恰好属于一个代理集群。

注 2

集群中的代理不需要在某个特定时间点都处于活跃状态。如果代理 A 创建另一个代理 B,之后 A 终止且 B 创建代理 C,如果 A 可以与 B 共享一些内存且 B 可以与 C 共享一些内存,则这三个代理在同一个集群中。

集群内的所有代理在其各自代理记录中的[[LittleEndian]]字段必须具有相同的值。

注 3

如果代理集群内不同的代理具有不同的[[LittleEndian]]值,则很难将共享内存用于多字节数据。

集群内的所有代理在其各自代理记录中的[[IsLockFree1]]字段必须具有相同的值;[[IsLockFree2]]字段也是如此。

集群内的所有代理在其各自代理记录中的[[Signifier]]字段必须具有不同的值。

嵌入可以在代理不知情或不配合的情况下停用(停止前进进度)或激活(恢复前进进度)代理。如果嵌入这样做,它不得让集群中的某些代理保持活跃状态,而集群中的其他代理被无限期地停用。

注 4

前述限制的目的是避免代理因为另一个代理被停用而死锁或饥饿的情况。例如,如果具有独立于任何窗口中文档的生命周期的 HTML 共享工作线程被允许与这种独立文档的专用工作线程共享内存,并且文档及其专用工作线程在专用工作线程持有锁时被停用(例如,文档被推入其窗口的历史记录),然后共享工作线程尝试获取锁,那么共享工作线程将被阻塞,直到专用工作线程再次被激活(如果有的话)。与此同时,试图从其他窗口访问共享工作线程的其他工作线程将饥饿。

此限制的含义是,不属于嵌入中同一暂停/唤醒集合的代理之间将无法共享内存。

嵌入可以在代理集群的其他代理事先不知情或不配合的情况下终止代理。如果代理不是通过自身或集群中另一个代理的程序动作终止,而是被集群外部的力量终止,那么嵌入必须选择两种策略之一:要么终止集群中的所有代理,要么提供可靠的 API,允许集群中的代理进行协调,使得集群的至少一个剩余成员能够检测到终止,终止数据包含足够的信息来标识被终止的代理

注 5

这种类型的终止的例子包括:操作系统或用户终止在单独进程中运行的代理;嵌入本身终止与其他代理在同一进程中运行的代理,当按代理的资源计算表明该代理失控时。

以下每个规范值以及从它们可传递到达的值都恰好属于一个代理集群。

在集群中任何代理对任何 ECMAScript 代码进行任何求值之前,集群中所有代理代理记录[[CandidateExecution]]字段被设置为初始候选执行。初始候选执行是一个空候选执行,其[[EventsRecords]]字段是一个列表,为每个代理包含一个代理事件记录,其[[AgentSignifier]]字段是该代理代理标识符,并且其[[EventList]][[AgentSynchronizesWith]]字段是空的列表

注 6

代理集群中的所有代理在其代理记录[[CandidateExecution]]字段中共享相同的候选执行候选执行内存模型使用的规范机制。

注 7

代理集群是一种规范机制,不需要对应 ECMAScript 实现的任何特定工件。

9.8 前进进度

代理取得前进进度是指其根据本规范执行求值步骤。

代理运行执行上下文同步且无限期地等待外部事件时,该代理变为阻塞状态。只有代理记录[[CanBlock]]字段为true代理才能在这种意义上变为阻塞状态。非阻塞代理是指不处于阻塞状态的代理。

实现必须确保:

这与内存模型中的活跃性保证一起,确保所有seq-cst写入最终对所有代理变为可观察的。

9.9 WeakRef 和 FinalizationRegistry 目标的处理模型

9.9.1 目标

本规范不保证任何对象或符号会被垃圾回收。不活跃的对象或符号可能在很长时间后被释放,或者永远不被释放。因此,本规范在描述由垃圾回收触发的行为时使用"可能"一词。

WeakRefsFinalizationRegistrys的语义基于在特定时间点发生的两个操作:

这两个动作(ClearKeptObjectsCleanupFinalizationRegistry)都不能中断同步 ECMAScript 执行。因为宿主可能组装更长的同步 ECMAScript 执行运行,本规范将ClearKeptObjectsCleanupFinalizationRegistry的调度推迟到宿主环境

一些 ECMAScript 实现包括在后台运行的垃圾收集器实现,包括当 ECMAScript 处于空闲状态时。让宿主环境调度CleanupFinalizationRegistry允许它恢复 ECMAScript 执行以运行终结器工作,这可能释放持有的值,减少整体内存使用。

9.9.2 活跃性

对于某个对象和/或符号集合S,关于S假设 WeakRef 无关执行是指这样的执行:其引用对象是S元素的WeakRef的抽象操作WeakRefDeref总是返回undefined

注 1
WeakRef无关性与活跃性一起捕获两个概念。一是WeakRef本身不会使其引用对象保持活跃。二是活跃性中的循环并不意味着值是活跃的。具体来说,如果确定v的活跃性依赖于确定WeakRef引用对象r的活跃性,则r的活跃性不能假设v的活跃性,这将是循环推理。
注 2
WeakRef无关性是在对象或符号集合上定义的,而不是在单个值上定义的,以考虑循环。如果它是在单个值上定义的,那么循环中的WeakRef引用对象将被认为是活跃的,即使其身份只能通过循环中的其他WeakRef引用对象观察到。
注 3
通俗地说,如果包含单个对象或符号的每个集合都是活跃的,我们就说该对象或符号是活跃的。

在求值期间的任何时点,如果满足以下任一条件,则对象和/或符号集合S被认为是活跃的

  • S中的任何元素都包含在任何代理[[KeptAlive]]列表中。
  • 存在一个关于S的有效未来假设 WeakRef 无关执行,该执行观察S中任何值的身份。
注 4
上述第二个条件旨在捕获这样的直觉:如果值的身份可以通过非WeakRef方式观察到,则该值是活跃的。值的身份可以通过观察严格相等比较或观察值被用作 Map 中的键来观察。
注 5

对象或符号在字段、内部槽或属性中的存在并不意味着该值是活跃的。例如,如果所讨论的值从未传回程序,那么它就无法被观察到。

WeakMap 中的键、WeakSet 的成员以及FinalizationRegistry单元记录的[[WeakRefTarget]][[UnregisterToken]]字段都是这种情况。

上述定义意味着,如果 WeakMap 中的键不是活跃的,那么其对应的值也不一定是活跃的。

注 6
活跃性是保证引擎不得清空哪些WeakRefs的下界。这里定义的活跃性是不可判定的。实际上,引擎使用保守的近似,如可达性。预期会有很大的实现自由度。

9.9.3 执行

在任何时候,如果对象和/或符号集合S不是活跃的,ECMAScript 实现可以原子地执行以下步骤:

  1. 对于S的每个元素value,执行
    1. 对于每个ref.[[WeakRefTarget]]valueWeakRef ref,执行
      1. 设置ref.[[WeakRefTarget]]empty
    2. 对于每个fg.[[Cells]]包含cell.[[WeakRefTarget]]value记录 cellFinalizationRegistry fg,执行
      1. 设置cell.[[WeakRefTarget]]empty
      2. 可选地,执行HostEnqueueFinalizationRegistryCleanupJob(fg)。
    3. 对于每个map.[[WeakMapData]]包含r.[[Key]]value记录 r的 WeakMap map,执行
      1. 设置r.[[Key]]empty
      2. 设置r.[[Value]]empty
    4. 对于每个set.[[WeakSetData]]包含value的 WeakSet set,执行
      1. 用值为empty的元素替换set.[[WeakSetData]]中值为value的元素。
注 1

与活跃性定义一起,本条款规定了实现可以应用于WeakRefs的优化。

可以在不观察对象身份的情况下访问对象。诸如死变量消除和对身份未被观察的非逃逸对象属性的标量替换等优化是允许的。因此,这些优化被允许可观察地清空指向此类对象的WeakRefs

另一方面,如果对象的身份是可观察的,并且该对象在WeakRef[[WeakRefTarget]]内部槽中,则禁止可观察地清空WeakRef的重新物化等优化。

因为调用HostEnqueueFinalizationRegistryCleanupJob是可选的,FinalizationRegistry中的注册对象不一定使该FinalizationRegistry保持活跃。实现可以因任何原因省略FinalizationRegistry回调,例如,如果FinalizationRegistry本身变为死亡,或者应用程序正在关闭。

注 2

实现没有义务为非活跃对象或符号的最大集合清空WeakRefs

如果实现选择一个非活跃集合S来清空WeakRefs,此定义要求它同时清空S中所有值的WeakRefs。换句话说,实现清空指向值vWeakRef而不清空其他WeakRefs(如果不清空,可能导致观察到v值的执行)是不符合规范的。

9.9.4 宿主钩子

9.9.4.1 HostEnqueueFinalizationRegistryCleanupJob ( finalizationRegistry )

宿主定义的抽象操作 HostEnqueueFinalizationRegistryCleanupJob 接收参数finalizationRegistry(一个FinalizationRegistry),并返回unused

cleanupJob为捕获finalizationRegistry的无参数新作业抽象闭包,调用时执行以下步骤:

  1. cleanupResultCompletion(CleanupFinalizationRegistry(finalizationRegistry))。
  2. 如果cleanupResult异常完成,执行任何宿主定义的错误报告步骤。
  3. 返回unused

HostEnqueueFinalizationRegistryCleanupJob 的实现调度cleanupJob在将来某个时间执行(如果可能)。它还必须符合9.5中的要求。

9.10 ClearKeptObjects ( )

抽象操作 ClearKeptObjects 不接收参数,并返回unused。预期 ECMAScript 实现在同步 ECMAScript 执行序列完成时调用 ClearKeptObjects。调用时执行以下步骤:

  1. agentRecord周围代理代理记录
  2. 设置agentRecord.[[KeptAlive]]为一个新的空列表
  3. 返回unused

9.11 AddToKeptObjects ( value )

抽象操作 AddToKeptObjects 接收参数value(一个对象或符号),并返回unused。调用时执行以下步骤:

  1. agentRecord周围代理代理记录
  2. value追加到agentRecord.[[KeptAlive]]
  3. 返回unused
当抽象操作 AddToKeptObjects 使用目标对象或符号调用时,它将目标添加到一个列表中,该列表将强引用目标,直到调用ClearKeptObjects

9.12 CleanupFinalizationRegistry ( finalizationRegistry )

抽象操作 CleanupFinalizationRegistry 接收参数finalizationRegistry(一个FinalizationRegistry),并返回包含unused正常完成抛出完成。调用时执行以下步骤:

  1. 断言finalizationRegistry具有[[Cells]][[CleanupCallback]]内部槽。
  2. callbackfinalizationRegistry.[[CleanupCallback]]
  3. finalizationRegistry.[[Cells]]包含cell.[[WeakRefTarget]]empty记录 cell时,实现可以执行以下步骤:
    1. 选择任何这样的cell
    2. finalizationRegistry.[[Cells]]中移除cell
    3. 执行? HostCallJobCallback(callback, undefined, « cell.[[HeldValue]] »)。
  4. 返回unused

9.13 CanBeHeldWeakly ( v )

抽象操作 CanBeHeldWeakly 接收参数v(一个ECMAScript 语言值),并返回一个布尔值。当且仅当v适合用作弱引用时,它返回true。只有适合用作弱引用的值才能作为 WeakMap 的键、WeakSet 的元素、WeakRef的目标或FinalizationRegistry的目标之一。调用时执行以下步骤:

  1. 如果v是对象,返回true
  2. 如果v是符号KeyForSymbol(v)为undefined,返回true
  3. 返回false

没有语言身份的语言值可以在没有先前引用的情况下体现,并且不适合用作弱引用。由Symbol.for产生的符号值与其他符号值不同,没有语言身份,不适合用作弱引用。知名符号可能永远不会被回收,但仍被视为适合用作弱引用,因为它们数量有限,因此可以通过各种实现方法进行管理。但是,在活跃 WeakMap 中与知名符号关联的任何值都不太可能被回收,并且在实现中可能"泄漏"内存资源。

10 普通对象和异构对象行为

10.1 普通对象内部方法和内部槽

所有普通对象都有一个名为[[Prototype]]的内部槽。此内部槽的值要么是null,要么是一个对象,用于实现继承。假设一个名为P的属性在普通对象 O中不存在,但在其[[Prototype]]对象上存在。如果P引用[[Prototype]]对象上的一个数据属性O对于get访问会继承它,使其表现得好像PO的一个属性。如果P引用[[Prototype]]对象上的一个可写数据属性,对OP的set访问会在O上创建一个名为P的新数据属性。如果P引用[[Prototype]]对象上的一个不可写数据属性,对OP的set访问会失败。如果P引用[[Prototype]]对象上的一个访问器属性O会继承该访问器用于get访问和set访问。

每个普通对象都有一个布尔值[[Extensible]]内部槽,用于满足6.1.7.3中指定的可扩展性相关内部方法不变量。也就是说,一旦对象的[[Extensible]]内部槽的值被设置为false,就不再可能向对象添加属性、修改对象的[[Prototype]]内部槽的值,或随后将[[Extensible]]的值更改为true

在以下算法描述中,假设O是一个普通对象P是一个属性键值,V是任何ECMAScript语言值Desc是一个属性描述符记录。

每个普通对象内部方法都委托给同名的抽象操作。如果这样的抽象操作依赖于另一个内部方法,那么内部方法在O上被调用,而不是直接调用同名的抽象操作。这些语义确保当普通对象内部方法应用于异构对象时,它们重写的内部方法会被调用。

10.1.1 [[GetPrototypeOf]] ( )

普通对象 O[[GetPrototypeOf]]内部方法不接受参数,返回一个包含Object或null正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryGetPrototypeOf(O)。

10.1.1.1 OrdinaryGetPrototypeOf ( O )

抽象操作OrdinaryGetPrototypeOf接受参数O(一个Object),返回一个Object或null。调用时执行以下步骤:

  1. 返回 O.[[Prototype]]

10.1.2 [[SetPrototypeOf]] ( V )

普通对象 O[[SetPrototypeOf]]内部方法接受参数V(一个Object或null),返回一个包含Boolean的正常完成。调用时执行以下步骤:

  1. 返回 OrdinarySetPrototypeOf(O, V)。

10.1.2.1 OrdinarySetPrototypeOf ( O, V )

抽象操作OrdinarySetPrototypeOf接受参数O(一个Object)和V(一个Object或null),返回一个Boolean。调用时执行以下步骤:

  1. currentO.[[Prototype]]
  2. 如果 SameValue(V, current) 为 true,返回 true
  3. extensibleO.[[Extensible]]
  4. 如果 extensiblefalse,返回 false
  5. pV
  6. donefalse
  7. 重复,当 donefalse 时,
    1. 如果 pnull,那么
      1. 设置 donetrue
    2. 否则如果 SameValue(p, O) 为 true,那么
      1. 返回 false
    3. 否则,
      1. 如果 p.[[GetPrototypeOf]] 不是10.1.1中定义的普通对象内部方法,设置 donetrue
      2. 否则,设置 pp.[[Prototype]]
  8. 设置 O.[[Prototype]]V
  9. 返回 true

步骤7中的循环保证在仅包含使用[[GetPrototypeOf]][[SetPrototypeOf]]普通对象定义的对象的任何原型链中都不会出现循环。

10.1.3 [[IsExtensible]] ( )

普通对象 O[[IsExtensible]]内部方法不接受参数,返回一个包含Boolean的正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryIsExtensible(O)。

10.1.3.1 OrdinaryIsExtensible ( O )

抽象操作OrdinaryIsExtensible接受参数O(一个Object),返回一个Boolean。调用时执行以下步骤:

  1. 返回 O.[[Extensible]]

10.1.4 [[PreventExtensions]] ( )

普通对象 O[[PreventExtensions]]内部方法不接受参数,返回一个包含true正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryPreventExtensions(O)。

10.1.4.1 OrdinaryPreventExtensions ( O )

抽象操作OrdinaryPreventExtensions接受参数O(一个Object),返回true。调用时执行以下步骤:

  1. 设置 O.[[Extensible]]false
  2. 返回 true

10.1.5 [[GetOwnProperty]] ( P )

普通对象 O[[GetOwnProperty]]内部方法接受参数P(一个属性键),返回一个包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryGetOwnProperty(O, P)。

10.1.5.1 OrdinaryGetOwnProperty ( O, P )

抽象操作OrdinaryGetOwnProperty接受参数O(一个Object)和P(一个属性键),返回一个属性描述符undefined。调用时执行以下步骤:

  1. 如果 O 没有键为 P 的自有属性,返回 undefined
  2. D 为一个新创建的没有字段的属性描述符
  3. XO 的键为 P 的自有属性。
  4. 如果 X 是一个数据属性,那么
    1. 设置 D.[[Value]]X[[Value]]特性的值。
    2. 设置 D.[[Writable]]X[[Writable]]特性的值。
  5. 否则,
    1. 断言X 是一个访问器属性
    2. 设置 D.[[Get]]X[[Get]]特性的值。
    3. 设置 D.[[Set]]X[[Set]]特性的值。
  6. 设置 D.[[Enumerable]]X[[Enumerable]]特性的值。
  7. 设置 D.[[Configurable]]X[[Configurable]]特性的值。
  8. 返回 D

10.1.6 [[DefineOwnProperty]] ( P, Desc )

普通对象 O[[DefineOwnProperty]]内部方法接受参数P(一个属性键)和Desc(一个属性描述符),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryDefineOwnProperty(O, P, Desc)。

10.1.6.1 OrdinaryDefineOwnProperty ( O, P, Desc )

抽象操作OrdinaryDefineOwnProperty接受参数O(一个Object)、P(一个属性键)和Desc(一个属性描述符),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. current 为 ? O.[[GetOwnProperty]](P)。
  2. extensible 为 ? IsExtensible(O)。
  3. 返回 ValidateAndApplyPropertyDescriptor(O, P, extensible, Desc, current)。

10.1.6.2 IsCompatiblePropertyDescriptor ( Extensible, Desc, Current )

抽象操作IsCompatiblePropertyDescriptor接受参数Extensible(一个Boolean)、Desc(一个属性描述符)和Current(一个属性描述符undefined),返回一个Boolean。调用时执行以下步骤:

  1. 返回 ValidateAndApplyPropertyDescriptor(undefined, "", Extensible, Desc, Current)。

10.1.6.3 ValidateAndApplyPropertyDescriptor ( O, P, extensible, Desc, current )

抽象操作ValidateAndApplyPropertyDescriptor接受参数O(一个Object或undefined)、P(一个属性键)、extensible(一个Boolean)、Desc(一个属性描述符)和current(一个属性描述符undefined),返回一个Boolean。当且仅当Desc可以作为具有指定extensibility和当前属性current的对象的属性应用,同时维护不变量时,它返回true。当这种应用是可能的且O不是undefined时,它对名为P的属性执行此操作(必要时创建该属性)。调用时执行以下步骤:

  1. 断言P是一个属性键
  2. 如果 currentundefined,那么
    1. 如果 extensiblefalse,返回 false
    2. 如果 Oundefined,返回 true
    3. 如果 IsAccessorDescriptor(Desc) 为 true,那么
      1. 在对象O上创建一个名为P的自有访问器属性,其[[Get]][[Set]][[Enumerable]][[Configurable]]特性分别设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    4. 否则,
      1. 在对象O上创建一个名为P的自有数据属性,其[[Value]][[Writable]][[Enumerable]][[Configurable]]特性分别设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    5. 返回 true
  3. 断言current是一个完全填充的属性描述符
  4. 如果 Desc 没有任何字段,返回 true
  5. 如果 current.[[Configurable]]false,那么
    1. 如果 Desc[[Configurable]]字段且Desc.[[Configurable]]true,返回 false
    2. 如果 Desc[[Enumerable]]字段且Desc.[[Enumerable]] 不等于 current.[[Enumerable]],返回 false
    3. 如果 IsGenericDescriptor(Desc) 为 falseIsAccessorDescriptor(Desc) 不等于 IsAccessorDescriptor(current),返回 false
    4. 如果 IsAccessorDescriptor(current) 为 true,那么
      1. 如果 Desc[[Get]]字段且SameValue(Desc.[[Get]], current.[[Get]]) 为 false,返回 false
      2. 如果 Desc[[Set]]字段且SameValue(Desc.[[Set]], current.[[Set]]) 为 false,返回 false
    5. 否则如果 current.[[Writable]]false,那么
      1. 如果 Desc[[Writable]]字段且Desc.[[Writable]]true,返回 false
      2. 注:SameValueNaN值返回true,这些值可能通过其他方式区分。在此处返回确保O的任何现有属性保持未修改。
      3. 如果 Desc[[Value]]字段,返回 SameValue(Desc.[[Value]], current.[[Value]])。
  6. 如果 O 不是 undefined,那么
    1. 如果 IsDataDescriptor(current) 为 trueIsAccessorDescriptor(Desc) 为 true,那么
      1. 如果 Desc[[Configurable]]字段,令 configurableDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 Desc[[Enumerable]]字段,令 enumerableDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象O的名为P的属性替换为一个访问器属性,其[[Configurable]][[Enumerable]]特性分别设置为configurableenumerable,其[[Get]][[Set]]特性设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    2. 否则如果 IsAccessorDescriptor(current) 为 trueIsDataDescriptor(Desc) 为 true,那么
      1. 如果 Desc[[Configurable]]字段,令 configurableDesc.[[Configurable]];否则令 configurablecurrent.[[Configurable]]
      2. 如果 Desc[[Enumerable]]字段,令 enumerableDesc.[[Enumerable]];否则令 enumerablecurrent.[[Enumerable]]
      3. 将对象O的名为P的属性替换为一个数据属性,其[[Configurable]][[Enumerable]]特性分别设置为configurableenumerable,其[[Value]][[Writable]]特性设置为Desc中对应字段的值(如果Desc有该字段),否则设置为该特性的默认值
    3. 否则,
      1. 对于Desc的每个字段,将对象O的名为P的属性的对应特性设置为该字段的值。
  7. 返回 true

10.1.7 [[HasProperty]] ( P )

普通对象 O[[HasProperty]]内部方法接受参数P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryHasProperty(O, P)。

10.1.7.1 OrdinaryHasProperty ( O, P )

抽象操作OrdinaryHasProperty接受参数O(一个Object)和P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. hasOwn 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 hasOwn 不是 undefined,返回 true
  3. parent 为 ? O.[[GetPrototypeOf]]()。
  4. 如果 parent 不是 null,那么
    1. 返回 ? parent.[[HasProperty]](P)。
  5. 返回 false

10.1.8 [[Get]] ( P, Receiver )

普通对象 O[[Get]]内部方法接受参数P(一个属性键)和Receiver(一个ECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryGet(O, P, Receiver)。

10.1.8.1 OrdinaryGet ( O, P, Receiver )

抽象操作OrdinaryGet接受参数O(一个Object)、P(一个属性键)和Receiver(一个ECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,那么
    1. parent 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 parentnull,返回 undefined
    3. 返回 ? parent.[[Get]](P, Receiver)。
  3. 如果 IsDataDescriptor(desc) 为 true,返回 desc.[[Value]]
  4. 断言IsAccessorDescriptor(desc) 为 true
  5. getterdesc.[[Get]]
  6. 如果 getterundefined,返回 undefined
  7. 返回 ? Call(getter, Receiver)。

10.1.9 [[Set]] ( P, V, Receiver )

普通对象 O[[Set]]内部方法接受参数P(一个属性键)、V(一个ECMAScript语言值)和Receiver(一个ECMAScript语言值),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinarySet(O, P, V, Receiver)。

10.1.9.1 OrdinarySet ( O, P, V, Receiver )

抽象操作OrdinarySet接受参数O(一个Object)、P(一个属性键)、V(一个ECMAScript语言值)和Receiver(一个ECMAScript语言值),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. ownDesc 为 ? O.[[GetOwnProperty]](P)。
  2. 返回 ? OrdinarySetWithOwnDescriptor(O, P, V, Receiver, ownDesc)。

10.1.9.2 OrdinarySetWithOwnDescriptor ( O, P, V, Receiver, ownDesc )

抽象操作OrdinarySetWithOwnDescriptor接受参数O(一个Object)、P(一个属性键)、V(一个ECMAScript语言值)、Receiver(一个ECMAScript语言值)和ownDesc(一个属性描述符undefined),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 ownDescundefined,那么
    1. parent 为 ? O.[[GetPrototypeOf]]()。
    2. 如果 parent 不是 null,那么
      1. 返回 ? parent.[[Set]](P, V, Receiver)。
    3. 否则,
      1. 设置 ownDesc 为属性描述符 { [[Value]]: undefined, [[Writable]]: true, [[Enumerable]]: true, [[Configurable]]: true }。
  2. 如果 IsDataDescriptor(ownDesc) 为 true,那么
    1. 如果 ownDesc.[[Writable]]false,返回 false
    2. 如果 Receiver 不是Object,返回 false
    3. existingDescriptor 为 ? Receiver.[[GetOwnProperty]](P)。
    4. 如果 existingDescriptor 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(existingDescriptor) 为 true,返回 false
      2. 如果 existingDescriptor.[[Writable]]false, 返回 false
      3. valueDesc 为属性描述符 { [[Value]]: V }。
      4. 返回 ? Receiver.[[DefineOwnProperty]](P, valueDesc)。
    5. 否则,
      1. 断言Receiver 当前没有属性 P
      2. 返回 ? CreateDataProperty(Receiver, P, V)。
  3. 断言IsAccessorDescriptor(ownDesc) 为 true
  4. setterownDesc.[[Set]]
  5. 如果 setterundefined,返回 false
  6. 执行 ? Call(setter, Receiver, « V »)。
  7. 返回 true

10.1.10 [[Delete]] ( P )

普通对象 O[[Delete]]内部方法接受参数P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? OrdinaryDelete(O, P)。

10.1.10.1 OrdinaryDelete ( O, P )

抽象操作OrdinaryDelete接受参数O(一个Object)和P(一个属性键),返回包含Boolean的正常完成抛出完成。调用时执行以下步骤:

  1. desc 为 ? O.[[GetOwnProperty]](P)。
  2. 如果 descundefined,返回 true
  3. 如果 desc.[[Configurable]]true,那么
    1. O 中移除名为 P 的自有属性。
    2. 返回 true
  4. 返回 false

10.1.11 [[OwnPropertyKeys]] ( )

普通对象 O[[OwnPropertyKeys]]内部方法不接受参数,返回一个包含属性键列表正常完成。调用时执行以下步骤:

  1. 返回 OrdinaryOwnPropertyKeys(O)。

10.1.11.1 OrdinaryOwnPropertyKeys ( O )

抽象操作OrdinaryOwnPropertyKeys接受参数O(一个Object),返回一个属性键列表。调用时执行以下步骤:

  1. keys 为一个新的空列表
  2. 对于 O 的每个自有属性键 P,满足 P数组索引,按升序数字索引顺序,执行
    1. P 追加到 keys
  3. 对于 O 的每个自有属性键 P,满足 P 是字符串P 不是数组索引,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  4. 对于 O 的每个自有属性键 P,满足 P 是Symbol,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  5. 返回 keys

10.1.12 OrdinaryObjectCreate ( proto [ , additionalInternalSlotsList ] )

抽象操作OrdinaryObjectCreate接受参数proto(一个Object或null)和可选参数additionalInternalSlotsList(内部插槽名称的列表),返回一个Object。它用于指定新普通对象的运行时创建。additionalInternalSlotsList包含除[[Prototype]][[Extensible]]之外必须作为对象一部分定义的附加内部插槽的名称。如果未提供additionalInternalSlotsList,则使用一个新的空列表。调用时执行以下步骤:

  1. internalSlotsList 为 « [[Prototype]], [[Extensible]] »。
  2. 如果 additionalInternalSlotsList 存在,设置 internalSlotsListinternalSlotsListadditionalInternalSlotsList列表连接
  3. OMakeBasicObject(internalSlotsList)。
  4. 设置 O.[[Prototype]]proto
  5. 返回 O

虽然OrdinaryObjectCreate除了调用MakeBasicObject之外没有做更多的事情,但它的使用传达了创建普通对象而不是奇异对象的意图。因此,在本规范中,任何随后以会使结果变成非普通对象的方式修改对象内部方法的算法都不会调用它。创建奇异对象的操作直接调用MakeBasicObject

10.1.13 OrdinaryCreateFromConstructor ( constructor, intrinsicDefaultProto [ , internalSlotsList ] )

抽象操作OrdinaryCreateFromConstructor接受参数constructor(一个函数对象)和intrinsicDefaultProto(一个字符串)以及可选参数internalSlotsList(内部插槽名称的列表),返回包含Object的正常完成抛出完成。它创建一个普通对象,其[[Prototype]]值从构造器"prototype"属性中检索(如果存在)。否则,由intrinsicDefaultProto命名的内在值用于[[Prototype]]internalSlotsList包含必须作为对象一部分定义的附加内部插槽的名称。如果未提供internalSlotsList,则使用一个新的空列表。调用时执行以下步骤:

  1. 断言intrinsicDefaultProto是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]]值的内在值。
  2. proto 为 ? GetPrototypeFromConstructor(constructor, intrinsicDefaultProto)。
  3. 如果 internalSlotsList 存在,令 slotsListinternalSlotsList
  4. 否则,令 slotsList 为一个新的空列表
  5. 返回 OrdinaryObjectCreate(proto, slotsList)。

10.1.14 GetPrototypeFromConstructor ( constructor, intrinsicDefaultProto )

抽象操作GetPrototypeFromConstructor接受参数constructor(一个函数对象)和intrinsicDefaultProto(一个字符串),返回包含Object的正常完成抛出完成。它确定应该用于创建对应于特定构造器的对象的[[Prototype]]值。该值从构造器"prototype"属性中检索(如果存在)。否则,由intrinsicDefaultProto命名的内在值用于[[Prototype]]。调用时执行以下步骤:

  1. 断言intrinsicDefaultProto是本规范的内在对象名称。对应的对象必须是旨在用作对象的[[Prototype]]值的内在值。
  2. proto 为 ? Get(constructor, "prototype")。
  3. 如果 proto 不是Object,那么
    1. realm 为 ? GetFunctionRealm(constructor)。
    2. 设置 protorealm 的名为 intrinsicDefaultProto 的内在对象。
  4. 返回 proto

如果constructor不提供[[Prototype]]值,则使用的默认值从constructor函数的领域获得,而不是从运行执行上下文获得。

10.1.15 RequireInternalSlot ( O, internalSlot )

抽象操作RequireInternalSlot接受参数O(一个ECMAScript语言值)和internalSlot(一个内部插槽名称),返回包含unused正常完成抛出完成。除非O 是Object且具有给定的内部插槽,否则它会抛出异常。调用时执行以下步骤:

  1. 如果 O 不是Object,抛出 TypeError 异常。
  2. 如果 O 没有 internalSlot 内部插槽,抛出 TypeError 异常。
  3. 返回 unused

10.2 ECMAScript函数对象

ECMAScript函数对象封装了在词法环境上封闭的参数化ECMAScript代码,并支持该代码的动态评估。ECMAScript函数对象是一个普通对象,具有与其他普通对象相同的内部插槽和相同的内部方法。ECMAScript函数对象的代码可以是严格模式代码11.2.2)或非严格代码。代码为严格模式代码的ECMAScript函数对象称为严格函数。代码不是严格模式代码的称为非严格函数

除了[[Extensible]][[Prototype]]之外,ECMAScript函数对象还具有表30中列出的内部插槽。

表30:ECMAScript函数对象的内部插槽
内部插槽 类型 描述
[[Environment]] 一个环境记录 函数封闭的环境记录。在评估函数代码时用作外部环境。
[[PrivateEnvironment]] 一个私有环境记录null 函数封闭的私有名称私有环境记录。如果此函数在语法上不包含在类中,则为null。在评估函数代码时用作内部类的外部私有环境。
[[FormalParameters]] 一个解析节点 定义函数形式参数列表的源文本的根解析节点。
[[ECMAScriptCode]] 一个解析节点 定义函数体的源文本的根解析节点。
[[ConstructorKind]] basederived 函数是否为派生类构造器
[[Realm]] 一个领域记录 创建函数的领域,它提供在评估函数时访问的任何内在对象。
[[ScriptOrModule]] 一个脚本记录或一个模块记录 创建函数的脚本或模块。
[[ThisMode]] lexicalstrictglobal 定义如何在函数的形式参数和代码体中解释this引用。lexical表示this引用词法封闭函数的this值。strict表示this值完全按照函数调用提供的使用。global表示undefinednullthis值被解释为对全局对象的引用,任何其他this值首先传递给ToObject
[[Strict]] 一个Boolean 如果这是严格函数则为true,如果这是非严格函数则为false
[[HomeObject]] 一个Object 如果函数使用super,这是其[[GetPrototypeOf]]提供super属性查找开始的对象的对象。
[[SourceText]] Unicode代码点序列 定义函数的源文本
[[Fields]] 类字段定义记录列表 如果函数是类,这是表示类的非静态字段和相应初始化器的记录列表。
[[PrivateMethods]] 私有元素列表 如果函数是类,这是表示类的非静态私有方法和访问器的列表。
[[ClassFieldInitializerName]] 一个字符串、一个Symbol、一个私有名称empty 如果函数是作为类字段的初始化器创建的,则为字段的命名评估使用的名称;否则为empty
[[IsClassConstructor]] 一个Boolean 指示函数是否为类构造器。(如果为true,调用函数的[[Call]]将立即抛出TypeError异常。)

所有ECMAScript函数对象都有此处定义的[[Call]]内部方法。同时也是构造器的ECMAScript函数另外还有[[Construct]]内部方法。

10.2.1 [[Call]] ( thisArgument, argumentsList )

ECMAScript函数对象 F[[Call]]内部方法接受参数thisArgument(一个ECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. calleeContextPrepareForOrdinaryCall(F, undefined)。
  3. 断言calleeContext现在是运行执行上下文
  4. 如果 F.[[IsClassConstructor]]true,那么
    1. error 为新创建的 TypeError 对象。
    2. 注:errorcalleeContext中使用F的关联领域记录创建。
    3. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
    4. 返回 ThrowCompletion(error)。
  5. 执行 OrdinaryCallBindThis(F, calleeContext, thisArgument)。
  6. resultCompletion(OrdinaryCallEvaluateBody(F, argumentsList))。
  7. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
  8. 如果 result返回完成,返回 result.[[Value]]
  9. 断言result抛出完成
  10. 返回 ? result

当在步骤7中从执行上下文栈中移除calleeContext时,如果它被挂起并保留以供可访问的生成器稍后恢复,则不得销毁它。

10.2.1.1 PrepareForOrdinaryCall ( F, newTarget )

抽象操作PrepareForOrdinaryCall接受参数F(一个ECMAScript函数对象)和newTarget(一个Object或undefined),返回一个执行上下文。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. calleeContext 为新的ECMAScript代码执行上下文
  3. 设置 calleeContext 的Function为 F
  4. calleeRealmF.[[Realm]]
  5. 设置 calleeContext领域calleeRealm
  6. 设置 calleeContext 的ScriptOrModule为 F.[[ScriptOrModule]]
  7. localEnvNewFunctionEnvironment(F, newTarget)。
  8. 设置 calleeContext 的LexicalEnvironment为 localEnv
  9. 设置 calleeContext 的VariableEnvironment为 localEnv
  10. 设置 calleeContext 的PrivateEnvironment为 F.[[PrivateEnvironment]]
  11. 如果 callerContext 尚未挂起,挂起 callerContext
  12. calleeContext 推入执行上下文栈calleeContext现在是运行执行上下文
  13. 注:此点之后产生的任何异常对象都与 calleeRealm 关联。
  14. 返回 calleeContext

10.2.1.2 OrdinaryCallBindThis ( F, calleeContext, thisArgument )

抽象操作OrdinaryCallBindThis接受参数F(一个ECMAScript函数对象)、calleeContext(一个执行上下文)和thisArgument(一个ECMAScript语言值),返回unused。调用时执行以下步骤:

  1. thisModeF.[[ThisMode]]
  2. 如果 thisModelexical,返回 unused
  3. calleeRealmF.[[Realm]]
  4. localEnvcalleeContext 的LexicalEnvironment。
  5. 如果 thisModestrict,那么
    1. thisValuethisArgument
  6. 否则,
    1. 如果 thisArgumentundefinednull,那么
      1. globalEnvcalleeRealm.[[GlobalEnv]]
      2. 断言globalEnv全局环境记录
      3. thisValueglobalEnv.[[GlobalThisValue]]
    2. 否则,
      1. thisValue 为 ! ToObject(thisArgument)。
      2. 注:ToObject使用calleeRealm产生包装器对象。
  7. 断言localEnv函数环境记录
  8. 断言:下一步永远不会返回突然完成,因为localEnv.[[ThisBindingStatus]]不是initialized
  9. 执行 ! BindThisValue(localEnv, thisValue)。
  10. 返回 unused

10.2.1.3 运行时语义:EvaluateBody

语法导向操作EvaluateBody接受参数functionObject(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回返回完成抛出完成。它在以下产生式上分段定义:

FunctionBody : FunctionStatementList
  1. 返回 ? FunctionBodyEvaluateFunctionBody,参数为 functionObjectargumentsList
ConciseBody : ExpressionBody
  1. 返回 ? ConciseBodyEvaluateConciseBody,参数为 functionObjectargumentsList
GeneratorBody : FunctionBody
  1. 返回 ? GeneratorBodyEvaluateGeneratorBody,参数为 functionObjectargumentsList
AsyncGeneratorBody : FunctionBody
  1. 返回 ? AsyncGeneratorBodyEvaluateAsyncGeneratorBody,参数为 functionObjectargumentsList
AsyncFunctionBody : FunctionBody
  1. 返回 ? AsyncFunctionBodyEvaluateAsyncFunctionBody,参数为 functionObjectargumentsList
AsyncConciseBody : ExpressionBody
  1. 返回 ? AsyncConciseBodyEvaluateAsyncConciseBody,参数为 functionObjectargumentsList
Initializer : = AssignmentExpression
  1. 断言argumentsList为空。
  2. 断言functionObject.[[ClassFieldInitializerName]]不是empty
  3. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 为 true,那么
    1. value 为 ? InitializerNamedEvaluation,参数为 functionObject.[[ClassFieldInitializerName]]
  4. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 返回 ReturnCompletion(value)。

尽管字段初始化器构成函数边界,但调用FunctionDeclarationInstantiation没有任何可观察的效果,因此被省略。

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言argumentsList为空。
  2. 返回 ? ClassStaticBlockBodyEvaluateClassStaticBlockBody,参数为 functionObject

10.2.1.4 OrdinaryCallEvaluateBody ( F, argumentsList )

抽象操作OrdinaryCallEvaluateBody接受参数F(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回返回完成抛出完成。调用时执行以下步骤:

  1. 返回 ? F.[[ECMAScriptCode]]EvaluateBody,参数为 FargumentsList

10.2.2 [[Construct]] ( argumentsList, newTarget )

ECMAScript函数对象 F[[Construct]]内部方法接受参数argumentsListECMAScript语言值列表)和newTarget(一个构造器),返回包含Object的正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. kindF.[[ConstructorKind]]
  3. 如果 kindbase,那么
    1. thisArgument 为 ? OrdinaryCreateFromConstructor(newTarget, "%Object.prototype%")。
  4. calleeContextPrepareForOrdinaryCall(F, newTarget)。
  5. 断言calleeContext现在是运行执行上下文
  6. 如果 kindbase,那么
    1. 执行 OrdinaryCallBindThis(F, calleeContext, thisArgument)。
    2. initializeResultCompletion(InitializeInstanceElements(thisArgument, F))。
    3. 如果 initializeResult突然完成,那么
      1. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
      2. 返回 ? initializeResult
  7. constructorEnvcalleeContext 的LexicalEnvironment。
  8. resultCompletion(OrdinaryCallEvaluateBody(F, argumentsList))。
  9. 执行上下文栈中移除calleeContext并恢复callerContext运行执行上下文
  10. 如果 result抛出完成,那么
    1. 返回 ? result
  11. 断言result返回完成
  12. 如果 result.[[Value]] 是Object,返回 result.[[Value]]
  13. 如果 kindbase,返回 thisArgument
  14. 如果 result.[[Value]] 不是 undefined,抛出 TypeError 异常。
  15. thisBinding 为 ? constructorEnv.GetThisBinding()。
  16. 断言thisBinding 是Object
  17. 返回 thisBinding

10.2.3 OrdinaryFunctionCreate ( functionPrototype, sourceText, ParameterList, Body, thisMode, env, privateEnv )

抽象操作OrdinaryFunctionCreate接受参数functionPrototype(一个Object)、sourceText(Unicode代码点序列)、ParameterList(一个解析节点)、Body(一个解析节点)、thisModelexical-thisnon-lexical-this)、env(一个环境记录)和privateEnv(一个私有环境记录null),返回一个ECMAScript函数对象。它用于指定运行时创建具有默认[[Call]]内部方法且没有[[Construct]]内部方法的新函数(尽管随后可能通过诸如MakeConstructor之类的操作添加一个)。sourceText是要创建的函数的语法定义的源文本。调用时执行以下步骤:

  1. internalSlotsList表30中列出的内部插槽。
  2. FOrdinaryObjectCreate(functionPrototype, internalSlotsList)。
  3. 设置 F.[[Call]]10.2.1中指定的定义。
  4. 设置 F.[[SourceText]]sourceText
  5. 设置 F.[[FormalParameters]]ParameterList
  6. 设置 F.[[ECMAScriptCode]]Body
  7. StrictIsStrict(Body)。
  8. 设置 F.[[Strict]]Strict
  9. 如果 thisModelexical-this,设置 F.[[ThisMode]]lexical
  10. 否则,如果 Stricttrue,设置 F.[[ThisMode]]strict
  11. 否则,设置 F.[[ThisMode]]global
  12. 设置 F.[[IsClassConstructor]]false
  13. 设置 F.[[Environment]]env
  14. 设置 F.[[PrivateEnvironment]]privateEnv
  15. 设置 F.[[ScriptOrModule]]GetActiveScriptOrModule()。
  16. 设置 F.[[Realm]]当前领域记录
  17. 设置 F.[[HomeObject]]undefined
  18. 设置 F.[[Fields]] 为新的空列表
  19. 设置 F.[[PrivateMethods]] 为新的空列表
  20. 设置 F.[[ClassFieldInitializerName]]empty
  21. lenParameterListExpectedArgumentCount
  22. 执行 SetFunctionLength(F, len)。
  23. 返回 F

10.2.4 AddRestrictedFunctionProperties ( F, realm )

抽象操作AddRestrictedFunctionProperties接受参数F(一个函数对象)和realm(一个领域记录),返回unused。调用时执行以下步骤:

  1. 断言realm.[[Intrinsics]].[[%ThrowTypeError%]]存在且已被初始化。
  2. throwerrealm.[[Intrinsics]].[[%ThrowTypeError%]]。
  3. 执行 ! DefinePropertyOrThrow(F, "caller", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  4. 执行 ! DefinePropertyOrThrow(F, "arguments", PropertyDescriptor { [[Get]]: thrower, [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: true })。
  5. 返回 unused

10.2.4.1 %ThrowTypeError% ( )

此函数是%ThrowTypeError%内在对象。

它是一个匿名的内置函数对象,为每个领域定义一次。

调用时执行以下步骤:

  1. 抛出 TypeError 异常。

此函数的[[Extensible]]内部插槽的值为false

此函数的"length"属性具有特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

此函数的"name"属性具有特性{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

10.2.5 MakeConstructor ( F [ , writablePrototype [ , prototype ] ] )

抽象操作MakeConstructor接受参数F(一个ECMAScript函数对象或内置函数对象)和可选参数writablePrototype(一个Boolean)和prototype(一个Object),返回unused。它将F转换为构造器。调用时执行以下步骤:

  1. 如果 F 是ECMAScript函数对象,那么
    1. 断言IsConstructor(F) 为 false
    2. 断言F是一个可扩展对象,且没有"prototype"自身属性。
    3. 设置 F.[[Construct]]10.2.2中指定的定义。
  2. 否则,
    1. 设置 F.[[Construct]]10.3.2中指定的定义。
  3. 设置 F.[[ConstructorKind]]base
  4. 如果 writablePrototype 不存在,设置 writablePrototypetrue
  5. 如果 prototype 不存在,那么
    1. 设置 prototypeOrdinaryObjectCreate(%Object.prototype%)。
    2. 执行 ! DefinePropertyOrThrow(prototype, "constructor", PropertyDescriptor { [[Value]]: F, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: true })。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: writablePrototype, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 unused

10.2.6 MakeClassConstructor ( F )

抽象操作MakeClassConstructor接受参数F(一个ECMAScript函数对象),返回unused。调用时执行以下步骤:

  1. 断言F.[[IsClassConstructor]]false
  2. 设置 F.[[IsClassConstructor]]true
  3. 返回 unused

10.2.7 MakeMethod ( F, homeObject )

抽象操作MakeMethod接受参数F(一个ECMAScript函数对象)和homeObject(一个Object),返回unused。它将F配置为方法。调用时执行以下步骤:

  1. 断言homeObject普通对象
  2. 设置 F.[[HomeObject]]homeObject
  3. 返回 unused

10.2.8 DefineMethodProperty ( homeObject, key, closure, enumerable )

抽象操作DefineMethodProperty接受参数homeObject(一个Object)、key(一个属性键私有名称)、closure(一个函数对象)和enumerable(一个Boolean),返回包含私有元素unused正常完成,或突然完成。调用时执行以下步骤:

  1. 断言homeObject是普通的、可扩展的对象。
  2. 如果 key私有名称,那么
    1. 返回 私有元素 { [[Key]]: key, [[Kind]]: method, [[Value]]: closure }。
  3. 否则,
    1. desc 为PropertyDescriptor { [[Value]]: closure, [[Writable]]: true, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(homeObject, key, desc)。
    3. 注:DefinePropertyOrThrow仅在尝试定义key"prototype"的类静态方法时返回突然完成
    4. 返回 unused

10.2.9 SetFunctionName ( F, name [ , prefix ] )

抽象操作SetFunctionName接受参数F(一个函数对象)和name(一个属性键私有名称)和可选参数prefix(一个String),返回unused。它为F添加"name"属性。调用时执行以下步骤:

  1. 断言F是可扩展对象且没有"name"自身属性。
  2. 如果 name 是Symbol,那么
    1. descriptionname[[Description]]值。
    2. 如果 descriptionundefined,设置 name 为空字符串。
    3. 否则,设置 name"["description"]"字符串连接
  3. 否则,如果 name私有名称,那么
    1. 设置 namename.[[Description]]
  4. 如果 F[[InitialName]]内部插槽,那么
    1. 设置 F.[[InitialName]]name
  5. 如果 prefix 存在,那么
    1. 设置 nameprefix、代码单元0x0020(空格)和name字符串连接
    2. 如果 F[[InitialName]]内部插槽,那么
      1. 可选地,设置 F.[[InitialName]]name
  6. 执行 ! DefinePropertyOrThrow(F, "name", PropertyDescriptor { [[Value]]: name, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  7. 返回 unused

10.2.10 SetFunctionLength ( F, length )

抽象操作SetFunctionLength接受参数F(一个函数对象)和length(非负整数或+∞),返回unused。它为F添加"length"属性。调用时执行以下步骤:

  1. 断言F是可扩展对象且没有"length"自身属性。
  2. 执行 ! DefinePropertyOrThrow(F, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true })。
  3. 返回 unused

10.2.11 FunctionDeclarationInstantiation ( func, argumentsList )

抽象操作FunctionDeclarationInstantiation接受参数func(一个ECMAScript函数对象)和argumentsListECMAScript语言值列表),返回包含unused正常完成突然完成func是正在为其建立执行上下文函数对象

注1

当为评估ECMAScript函数建立执行上下文时,会创建新的函数环境记录,并在该环境记录中实例化每个形参的绑定。函数体中的每个声明也会被实例化。如果函数的形参不包含任何默认值初始化器,则函数体声明会在与参数相同的环境记录中实例化。如果存在默认值参数初始化器,则为函数体声明创建第二个环境记录。形参和函数作为FunctionDeclarationInstantiation的一部分被初始化。所有其他绑定在函数体评估期间被初始化。

调用时执行以下步骤:

  1. calleeContext运行执行上下文
  2. codefunc.[[ECMAScriptCode]]
  3. strictfunc.[[Strict]]
  4. formalsfunc.[[FormalParameters]]
  5. parameterNamesformalsBoundNames
  6. 如果 parameterNames 有任何重复条目,令 hasDuplicatestrue。否则,令 hasDuplicatesfalse
  7. simpleParameterListformalsIsSimpleParameterList
  8. hasParameterExpressionsformalsContainsExpression
  9. varNamescodeVarDeclaredNames
  10. varDeclarationscodeVarScopedDeclarations
  11. lexicalNamescodeLexicallyDeclaredNames
  12. functionNames 为新的空列表
  13. functionsToInitialize 为新的空列表
  14. 对于 varDeclarations 的每个元素 d,按反向列表顺序,执行
    1. 如果 d 既不是VariableDeclaration,也不是ForBinding,也不是BindingIdentifier,那么
      1. 断言d 要么是FunctionDeclaration,要么是GeneratorDeclaration,要么是AsyncFunctionDeclaration,要么是AsyncGeneratorDeclaration
      2. fndBoundNames的唯一元素。
      3. 如果 functionNames 不包含 fn,那么
        1. fn 作为第一个元素插入 functionNames
        2. 注:如果有多个同名函数声明,使用最后一个声明。
        3. d 作为第一个元素插入 functionsToInitialize
  15. argumentsObjectNeededtrue
  16. 如果 func.[[ThisMode]]lexical,那么
    1. 注:箭头函数从不有arguments对象。
    2. 设置 argumentsObjectNeededfalse
  17. 否则,如果 parameterNames 包含 "arguments",那么
    1. 设置 argumentsObjectNeededfalse
  18. 否则,如果 hasParameterExpressionsfalse,那么
    1. 如果 functionNames 包含 "arguments"lexicalNames 包含 "arguments",那么
      1. 设置 argumentsObjectNeededfalse
  19. 如果 stricttruehasParameterExpressionsfalse,那么
    1. 注:由于严格模式代码中对eval的调用不能创建在eval之外可见的新绑定,因此参数只需要单一的环境记录
    2. envcalleeContext 的LexicalEnvironment。
  20. 否则,
    1. 注:需要单独的环境记录以确保形参列表中直接eval调用创建的绑定位于声明参数的环境之外。
    2. calleeEnvcalleeContext 的LexicalEnvironment。
    3. envNewDeclarativeEnvironment(calleeEnv)。
    4. 断言calleeContext 的VariableEnvironment和 calleeEnv 是同一个环境记录
    5. 设置 calleeContext 的LexicalEnvironment为 env
  21. 对于 parameterNames 的每个字符串 paramName,执行
    1. alreadyDeclared 为 ! env.HasBinding(paramName)。
    2. 注:早期错误确保重复参数名只能出现在没有参数默认值或剩余参数的非严格函数中。
    3. 如果 alreadyDeclaredfalse,那么
      1. 执行 ! env.CreateMutableBinding(paramName, false)。
      2. 如果 hasDuplicatestrue,那么
        1. 执行 ! env.InitializeBinding(paramName, undefined)。
  22. 如果 argumentsObjectNeededtrue,那么
    1. 如果 stricttruesimpleParameterListfalse,那么
      1. aoCreateUnmappedArgumentsObject(argumentsList)。
    2. 否则,
      1. 注:映射的参数对象仅为没有剩余参数、任何参数默认值初始化器或任何解构参数的非严格函数提供。
      2. aoCreateMappedArgumentsObject(func, formals, argumentsList, env)。
    3. 如果 stricttrue,那么
      1. 执行 ! env.CreateImmutableBinding("arguments", false)。
      2. 注:在严格模式代码中,早期错误防止尝试赋值给此绑定,因此其可变性不可观察。
    4. 否则,
      1. 执行 ! env.CreateMutableBinding("arguments", false)。
    5. 执行 ! env.InitializeBinding("arguments", ao)。
    6. parameterBindingsparameterNames 和 « "arguments" » 的列表连接
  23. 否则,
    1. parameterBindingsparameterNames
  24. iteratorRecordCreateListIteratorRecord(argumentsList)。
  25. 如果 hasDuplicatestrue,那么
    1. 执行 ? formalsIteratorBindingInitialization,参数为 iteratorRecordundefined
  26. 否则,
    1. 执行 ? formalsIteratorBindingInitialization,参数为 iteratorRecordenv
  27. 如果 hasParameterExpressionsfalse,那么
    1. 注:参数和顶级var只需要单一的环境记录
    2. instantiatedVarNames列表 parameterBindings 的副本。
    3. 对于 varNames 的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! env.CreateMutableBinding(n, false)。
        3. 执行 ! env.InitializeBinding(n, undefined)。
    4. varEnvenv
  28. 否则,
    1. 注:需要单独的环境记录以确保形参列表中表达式创建的闭包不能看到函数体中的声明。
    2. varEnvNewDeclarativeEnvironment(env)。
    3. 设置 calleeContext 的VariableEnvironment为 varEnv
    4. instantiatedVarNames 为新的空列表
    5. 对于 varNames 的每个元素 n,执行
      1. 如果 instantiatedVarNames 不包含 n,那么
        1. n 追加到 instantiatedVarNames
        2. 执行 ! varEnv.CreateMutableBinding(n, false)。
        3. 如果 parameterBindings 不包含 n,或如果 functionNames 包含 n,那么
          1. initialValueundefined
        4. 否则,
          1. initialValue 为 ! env.GetBindingValue(n, false)。
        5. 执行 ! varEnv.InitializeBinding(n, initialValue)。
        6. 注:与形参同名的var最初具有与相应初始化参数相同的值。
  29. 注:附录B.3.2.1在此处添加了额外的步骤。
  30. 如果 strictfalse,那么
    1. lexEnvNewDeclarativeEnvironment(varEnv)。
    2. 注:非严格函数对顶级词法声明使用单独的环境记录,以便直接eval可以确定eval代码引入的任何var作用域声明是否与预先存在的顶级词法作用域声明冲突。这对于严格函数不是必需的,因为严格的直接eval总是将所有声明放入新的环境记录中。
  31. 否则,
    1. lexEnvvarEnv
  32. 设置 calleeContext 的LexicalEnvironment为 lexEnv
  33. lexDeclarationscodeLexicallyScopedDeclarations
  34. 对于 lexDeclarations 的每个元素 d,执行
    1. 注:词法声明的名称不能与函数/生成器声明、形参或var名称相同。词法声明的名称仅在此处实例化但未初始化。
    2. 对于 dBoundNames的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ! lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! lexEnv.CreateMutableBinding(dn, false)。
  35. privateEnvcalleeContext 的PrivateEnvironment。
  36. 对于 functionsToInitialize 的每个解析节点 f,执行
    1. fnfBoundNames的唯一元素。
    2. fofInstantiateFunctionObject,参数为 lexEnvprivateEnv
    3. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  37. 返回 unused
注2

B.3.2为上述算法提供了扩展,这对于与早于ECMAScript 2015的ECMAScript的Web浏览器实现的向后兼容性是必需的。

10.3 内置函数对象

内置函数对象普通对象;它必须满足10.1中规定的普通对象的要求。

除了每个普通对象所需的内部插槽(见10.1)之外,内置函数对象还必须具有以下内部插槽:

  • [[Realm]],一个领域记录,表示创建函数的领域
  • [[InitialName]],一个字符串,是函数的初始名称。它被20.2.3.5使用。

内置函数对象[[Prototype]]内部插槽的初始值是%Function.prototype%,除非另有规定。

内置函数对象必须具有符合10.3.1中定义的[[Call]]内部方法。

内置函数对象当且仅当它被描述为"构造器",或者本规范中的某个算法明确设置其[[Construct]]内部方法时,才具有[[Construct]]内部方法。这样的[[Construct]]内部方法必须符合10.3.2中的定义。

实现可以提供本规范中未定义的其他内置函数对象

10.3.1 [[Call]] ( thisArgument, argumentsList )

内置函数对象 F[[Call]]内部方法接受参数thisArgumentECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. 返回 ? BuiltinCallOrConstruct(F, thisArgument, argumentsList, undefined)。

10.3.2 [[Construct]] ( argumentsList, newTarget )

内置函数对象 F[[Construct]]内部方法(当该方法存在时)接受参数argumentsListECMAScript语言值列表)和newTarget(一个构造器),返回包含Object的正常完成抛出完成。调用时执行以下步骤:

  1. result 为 ? BuiltinCallOrConstruct(F, uninitialized, argumentsList, newTarget)。
  2. 断言result 是Object
  3. 返回 result

10.3.3 BuiltinCallOrConstruct ( F, thisArgument, argumentsList, newTarget )

抽象操作BuiltinCallOrConstruct接受参数F(内置函数对象)、thisArgumentECMAScript语言值uninitialized)、argumentsListECMAScript语言值列表)和newTarget构造器undefined),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. callerContext运行执行上下文
  2. 如果 callerContext 尚未被挂起,挂起 callerContext
  3. calleeContext 为新的执行上下文
  4. 设置 calleeContext 的Function为 F
  5. calleeRealmF.[[Realm]]
  6. 设置 calleeContext领域calleeRealm
  7. 设置 calleeContext 的ScriptOrModule为 null
  8. 执行 calleeContext 的任何必要的实现定义的初始化。
  9. calleeContext 推入执行上下文栈calleeContext 现在是运行执行上下文
  10. result完成记录,其为评估结果,以符合 F 规范的方式评估 F。如果 thisArgumentuninitialized,则 this 值未初始化;否则,thisArgument 提供 this 值。argumentsList 提供具名参数。newTarget 提供NewTarget值。
  11. 注:如果 F 在本文档中定义,"F 的规范"是通过算法步骤或其他方式为其指定的行为。
  12. 执行上下文栈中移除 calleeContext 并将 callerContext 恢复为运行执行上下文
  13. 返回 ? result

当从执行上下文栈中移除 calleeContext 时,如果它已被挂起并被可访问的生成器保留以供稍后恢复,则不得销毁它。

10.3.4 CreateBuiltinFunction ( behaviour, length, name, additionalInternalSlotsList [ , realm [ , prototype [ , prefix ] ] ] )

抽象操作CreateBuiltinFunction接受参数behaviour抽象闭包、一组算法步骤或本规范中提供的函数行为的某些其他定义)、length(非负整数或+∞)、name属性键私有名称)和additionalInternalSlotsList(内部插槽名称的列表)和可选参数realm领域记录)、prototype(Object或null)和prefix(字符串),返回内置函数对象additionalInternalSlotsList 包含必须作为对象的一部分定义的其他内部插槽的名称。此操作创建内置函数对象。调用时执行以下步骤:

  1. 如果 realm 不存在,设置 realm当前领域记录
  2. 如果 prototype 不存在,设置 prototyperealm.[[Intrinsics]].[[%Function.prototype%]]。
  3. internalSlotsList列表,包含10.3为即将创建的内置函数对象所需的所有内部插槽的名称。
  4. additionalInternalSlotsList 的元素追加到 internalSlotsList
  5. func 为新的内置函数对象,当调用时,使用提供的参数作为 behaviour 指定的相应参数的值,执行 behaviour 描述的操作。新的函数对象具有名称为 internalSlotsList 元素的内部插槽,以及 [[InitialName]] 内部插槽。
  6. 设置 func.[[Prototype]]prototype
  7. 设置 func.[[Extensible]]true
  8. 设置 func.[[Realm]]realm
  9. 设置 func.[[InitialName]]null
  10. 执行 SetFunctionLength(func, length)。
  11. 如果 prefix 不存在,那么
    1. 执行 SetFunctionName(func, name)。
  12. 否则,
    1. 执行 SetFunctionName(func, name, prefix)。
  13. 返回 func

本规范中定义的每个内置函数都是通过调用CreateBuiltinFunction抽象操作创建的。

10.4 内置异质对象内部方法和插槽

本规范定义了几种内置异质对象。这些对象通常表现得像普通对象,除了一些特定情况。以下异质对象使用普通对象的内部方法,除非在下面明确指定了其他方法:

10.4.1 绑定函数异质对象

绑定函数异质对象是一个异质对象,它包装另一个函数对象绑定函数异质对象是可调用的(它有[[Call]]内部方法,可能有[[Construct]]内部方法)。调用绑定函数异质对象通常会调用其包装的函数。

如果对象的[[Call]]和(如果适用)[[Construct]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是绑定函数异质对象。这些方法在BoundFunctionCreate中安装。

绑定函数异质对象没有表30中列出的ECMAScript函数对象的内部插槽。相反,除了[[Prototype]][[Extensible]]之外,它们还有表31中列出的内部插槽。

表31:绑定函数异质对象的内部插槽
内部插槽 类型 描述
[[BoundTargetFunction]] 可调用对象 被包装的函数对象
[[BoundThis]] ECMAScript语言值 调用包装函数时总是作为this值传递的值。
[[BoundArguments]] ECMAScript语言值列表 一个值列表,其元素用作对包装函数的任何调用的前几个参数。

10.4.1.1 [[Call]] ( thisArgument, argumentsList )

绑定函数异质对象 F[[Call]]内部方法接受参数thisArgumentECMAScript语言值)和argumentsListECMAScript语言值列表),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. targetF.[[BoundTargetFunction]]
  2. boundThisF.[[BoundThis]]
  3. boundArgsF.[[BoundArguments]]
  4. argsboundArgsargumentsList列表连接
  5. 返回 ? Call(target, boundThis, args)。

10.4.1.2 [[Construct]] ( argumentsList, newTarget )

绑定函数异质对象 F[[Construct]]内部方法接受参数argumentsListECMAScript语言值列表)和newTarget构造器),返回包含对象的正常完成抛出完成。调用时执行以下步骤:

  1. targetF.[[BoundTargetFunction]]
  2. 断言IsConstructor(target) 为 true
  3. boundArgsF.[[BoundArguments]]
  4. argsboundArgsargumentsList列表连接
  5. 如果 SameValue(F, newTarget) 为 true,设置 newTargettarget
  6. 返回 ? Construct(target, args, newTarget)。

10.4.1.3 BoundFunctionCreate ( targetFunction, boundThis, boundArgs )

抽象操作BoundFunctionCreate接受参数targetFunction函数对象)、boundThisECMAScript语言值)和boundArgsECMAScript语言值列表),返回包含函数对象正常完成抛出完成。它用于指定新绑定函数异质对象的创建。调用时执行以下步骤:

  1. proto 为 ? targetFunction.[[GetPrototypeOf]]()。
  2. internalSlotsList 为 « [[Prototype]], [[Extensible]] » 和表31中列出的内部插槽的列表连接
  3. objMakeBasicObject(internalSlotsList)。
  4. 设置 obj.[[Prototype]]proto
  5. 按照10.4.1.1中的描述设置 obj.[[Call]]
  6. 如果 IsConstructor(targetFunction) 为 true,那么
    1. 按照10.4.1.2中的描述设置 obj.[[Construct]]
  7. 设置 obj.[[BoundTargetFunction]]targetFunction
  8. 设置 obj.[[BoundThis]]boundThis
  9. 设置 obj.[[BoundArguments]]boundArgs
  10. 返回 obj

10.4.2 数组异质对象

数组是一个异质对象,它对数组索引属性键给予特殊处理(见6.1.7)。属性名数组索引的属性也称为元素。每个数组都有一个不可配置的"length"属性,其值始终是非负整数,其数学值严格小于232"length"属性的值在数值上大于名称为数组索引的每个自有属性的名称;每当创建或更改数组的自有属性时,会根据需要调整其他属性以维持此不变性。具体来说,每当添加名称为数组索引的自有属性时,如有必要,"length"属性的值会更改为该数组索引的数值加一;每当"length"属性的值更改时,名称为数组索引且值不小于新长度的每个自有属性都会被删除。此约束仅适用于数组的自有属性,不受可能从其原型继承的"length"数组索引属性的影响。

如果对象的[[DefineOwnProperty]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是数组异质对象(或简称数组)。这些方法在ArrayCreate中安装。

10.4.2.1 [[DefineOwnProperty]] ( P, Desc )

数组异质对象 A[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 P"length",那么
    1. 返回 ? ArraySetLength(A, Desc)。
  2. 否则,如果 P数组索引,那么
    1. lengthDescOrdinaryGetOwnProperty(A, "length")。
    2. 断言lengthDesc 不是 undefined
    3. 断言IsDataDescriptor(lengthDesc) 为 true
    4. 断言lengthDesc.[[Configurable]]false
    5. lengthlengthDesc.[[Value]]
    6. 断言length 是非负整数
    7. index 为 ! ToUint32(P)。
    8. 如果 indexlengthlengthDesc.[[Writable]]false,返回 false
    9. succeeded 为 ! OrdinaryDefineOwnProperty(A, P, Desc)。
    10. 如果 succeededfalse,返回 false
    11. 如果 indexlength,那么
      1. 设置 lengthDesc.[[Value]]index + 1𝔽
      2. 设置 succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", lengthDesc)。
      3. 断言succeededtrue
    12. 返回 true
  3. 返回 ? OrdinaryDefineOwnProperty(A, P, Desc)。

10.4.2.2 ArrayCreate ( length [ , proto ] )

抽象操作ArrayCreate接受参数length(非负整数)和可选参数proto(对象),返回包含数组异质对象正常完成抛出完成。它用于指定新数组的创建。调用时执行以下步骤:

  1. 如果 length > 232 - 1,抛出 RangeError 异常。
  2. 如果 proto 不存在,设置 proto%Array.prototype%
  3. AMakeBasicObject[[Prototype]], [[Extensible]] »)。
  4. 设置 A.[[Prototype]]proto
  5. 按照10.4.2.1中指定的设置 A.[[DefineOwnProperty]]
  6. 执行 ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 A

10.4.2.3 ArraySpeciesCreate ( originalArray, length )

抽象操作ArraySpeciesCreate接受参数originalArray(对象)和length(非负整数),返回包含对象的正常完成抛出完成。它用于指定使用从originalArray派生的构造器函数创建新数组或类似对象。它不强制构造器函数返回数组。调用时执行以下步骤:

  1. isArray 为 ? IsArray(originalArray)。
  2. 如果 isArrayfalse,返回 ? ArrayCreate(length)。
  3. C 为 ? Get(originalArray, "constructor")。
  4. 如果 IsConstructor(C) 为 true,那么
    1. thisRealm当前领域记录
    2. realmC 为 ? GetFunctionRealm(C)。
    3. 如果 thisRealmrealmC 不是同一个领域记录,那么
      1. 如果 SameValue(C, realmC.[[Intrinsics]].[[%Array%]]) 为 true,设置 Cundefined
  5. 如果 C 是对象,那么
    1. 设置 C 为 ? Get(C, %Symbol.species%)。
    2. 如果 Cnull,设置 Cundefined
  6. 如果 Cundefined,返回 ? ArrayCreate(length)。
  7. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  8. 返回 ? Construct(C, « 𝔽(length) »)。

如果originalArray是使用不是运行执行上下文领域领域的标准内置数组构造器创建的,那么使用运行执行上下文领域创建新数组。这与Web浏览器的历史行为保持兼容,这些浏览器历史上对现在使用ArraySpeciesCreate定义的Array.prototype方法有这种行为。

10.4.2.4 ArraySetLength ( A, Desc )

抽象操作ArraySetLength接受参数A(数组)和Desc属性描述符),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 Desc 没有 [[Value]] 字段,那么
    1. 返回 ! OrdinaryDefineOwnProperty(A, "length", Desc)。
  2. newLenDescDesc 的副本。
  3. newLen 为 ? ToUint32(Desc.[[Value]])。
  4. numberLen 为 ? ToNumber(Desc.[[Value]])。
  5. 如果 SameValueZero(newLen, numberLen) 为 false,抛出 RangeError 异常。
  6. 设置 newLenDesc.[[Value]]newLen
  7. oldLenDescOrdinaryGetOwnProperty(A, "length")。
  8. 断言oldLenDesc 不是 undefined
  9. 断言IsDataDescriptor(oldLenDesc) 为 true
  10. 断言oldLenDesc.[[Configurable]]false
  11. oldLenoldLenDesc.[[Value]]
  12. 如果 newLenoldLen,那么
    1. 返回 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
  13. 如果 oldLenDesc.[[Writable]]false,返回 false
  14. 如果 newLenDesc 没有 [[Writable]] 字段或 newLenDesc.[[Writable]]true,那么
    1. newWritabletrue
  15. 否则,
    1. 注:如果任何元素无法删除,将[[Writable]]属性设置为false会被延迟。
    2. newWritablefalse
    3. 设置 newLenDesc.[[Writable]]true
  16. succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
  17. 如果 succeededfalse,返回 false
  18. 对于 A 的每个自有属性键 P,如果 P数组索引且 ! ToUint32(P) ≥ newLen,按数值索引降序执行
    1. deleteSucceeded 为 ! A.[[Delete]](P)。
    2. 如果 deleteSucceededfalse,那么
      1. 设置 newLenDesc.[[Value]] 为 ! ToUint32(P) + 1𝔽
      2. 如果 newWritablefalse,设置 newLenDesc.[[Writable]]false
      3. 执行 ! OrdinaryDefineOwnProperty(A, "length", newLenDesc)。
      4. 返回 false
  19. 如果 newWritablefalse,那么
    1. 设置 succeeded 为 ! OrdinaryDefineOwnProperty(A, "length", PropertyDescriptor { [[Writable]]: false })。
    2. 断言succeededtrue
  20. 返回 true

在步骤34中,如果Desc.[[Value]]是对象,则其valueOf方法会被调用两次。这是传统行为,从本规范第2版开始就以此效果进行了指定。

10.4.3 字符串异质对象

字符串对象是一个异质对象,它封装一个字符串值并暴露对应于字符串值各个码元元素的虚拟整数索引的数据属性字符串异质对象总是有一个名为"length"数据属性,其值是封装的字符串值的长度。码元数据属性"length"属性都是不可写和不可配置的。

如果对象的[[GetOwnProperty]][[DefineOwnProperty]][[OwnPropertyKeys]]内部方法使用以下实现,其他基本内部方法使用10.1中的定义,则该对象是字符串异质对象(或简称字符串对象)。这些方法在StringCreate中安装。

字符串异质对象具有与普通对象相同的内部插槽。它们还有一个[[StringData]]内部插槽。

10.4.3.1 [[GetOwnProperty]] ( P )

字符串异质对象 S[[GetOwnProperty]]内部方法接受参数P属性键),返回包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. descOrdinaryGetOwnProperty(S, P)。
  2. 如果 desc 不是 undefined,返回 desc
  3. 返回 StringGetOwnProperty(S, P)。

10.4.3.2 [[DefineOwnProperty]] ( P, Desc )

字符串异质对象 S[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成。调用时执行以下步骤:

  1. stringDescStringGetOwnProperty(S, P)。
  2. 如果 stringDesc 不是 undefined,那么
    1. extensibleS.[[Extensible]]
    2. 返回 IsCompatiblePropertyDescriptor(extensible, Desc, stringDesc)。
  3. 返回 ! OrdinaryDefineOwnProperty(S, P, Desc)。

10.4.3.3 [[OwnPropertyKeys]] ( )

字符串异质对象 O[[OwnPropertyKeys]]内部方法不接受参数,返回包含属性键列表正常完成。调用时执行以下步骤:

  1. keys 为新的空列表
  2. strO.[[StringData]]
  3. 断言str 是字符串
  4. lenstr 的长度。
  5. 对于每个整数 i,0 ≤ i < len,按升序执行
    1. 将 ! ToString(𝔽(i)) 追加到 keys
  6. 对于 O 的每个自有属性键 P,如果 P数组索引且 ! ToIntegerOrInfinity(P) ≥ len,按数值索引升序执行
    1. P 追加到 keys
  7. 对于 O 的每个自有属性键 P,如果 P 是字符串P 不是数组索引,按属性创建的时间升序执行
    1. P 追加到 keys
  8. 对于 O 的每个自有属性键 P,如果 P 是Symbol,按属性创建的时间升序执行
    1. P 追加到 keys
  9. 返回 keys

10.4.3.4 StringCreate ( value, prototype )

抽象操作StringCreate接受参数value(字符串)和prototype(对象),返回字符串异质对象。它用于指定新字符串异质对象的创建。调用时执行以下步骤:

  1. SMakeBasicObject[[Prototype]], [[Extensible]], [[StringData]] »)。
  2. 设置 S.[[Prototype]]prototype
  3. 设置 S.[[StringData]]value
  4. 按照10.4.3.1中指定的设置 S.[[GetOwnProperty]]
  5. 按照10.4.3.2中指定的设置 S.[[DefineOwnProperty]]
  6. 按照10.4.3.3中指定的设置 S.[[OwnPropertyKeys]]
  7. lengthvalue 的长度。
  8. 执行 ! DefinePropertyOrThrow(S, "length", PropertyDescriptor { [[Value]]: 𝔽(length), [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 S

10.4.3.5 StringGetOwnProperty ( S, P )

抽象操作StringGetOwnProperty接受参数S(具有[[StringData]]内部插槽的对象)和P属性键),返回属性描述符undefined。调用时执行以下步骤:

  1. 如果 P 不是字符串,返回 undefined
  2. indexCanonicalNumericIndexString(P)。
  3. 如果 index 不是整数,返回 undefined
  4. 如果 index-0𝔽index < -0𝔽,返回 undefined
  5. strS.[[StringData]]
  6. 断言str 是字符串
  7. lenstr 的长度。
  8. 如果 (index) ≥ len,返回 undefined
  9. resultStrstr(index) 到 (index) + 1 的子字符串
  10. 返回 PropertyDescriptor { [[Value]]: resultStr, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false }。

10.4.4 Arguments 异质对象

大多数ECMAScript函数向其代码提供一个arguments对象。根据函数定义的特征,其arguments对象要么是普通对象,要么是arguments异质对象Arguments异质对象是一个异质对象,其数组索引属性映射到其关联ECMAScript函数调用的形式参数绑定。

如果对象的内部方法使用以下实现,其他未在此指定的方法使用10.1中的实现,则该对象是arguments异质对象。这些方法在CreateMappedArgumentsObject中安装。

注1

虽然CreateUnmappedArgumentsObject被归组到此子句中,但它创建的是普通对象,而不是arguments异质对象

Arguments异质对象具有与普通对象相同的内部插槽。它们还有一个[[ParameterMap]]内部插槽。普通arguments对象也有一个[[ParameterMap]]内部插槽,其值始终是undefined。对于普通argument对象,[[ParameterMap]]内部插槽仅被Object.prototype.toString20.1.3.6)用于识别它们。

注2

Arguments异质对象整数索引的数据属性,其数值名称值小于对应函数对象的形式参数数量,最初与函数执行上下文中对应的参数绑定共享其值。这意味着更改属性会更改参数绑定的对应值,反之亦然。如果删除然后重新定义此类属性,或者将属性更改为访问器属性,则此对应关系会被破坏。如果arguments对象是普通对象,其属性值只是传递给函数的参数的副本,属性值与形式参数值之间没有动态链接。

注3

ParameterMap对象及其属性值被用作指定arguments对象与参数绑定对应关系的设备。ParameterMap对象和作为其属性值的对象不能从ECMAScript代码中直接观察到。ECMAScript实现不需要实际创建或使用此类对象来实现指定的语义。

注4

普通arguments对象定义一个名为"callee"的不可配置访问器属性,访问时抛出TypeError异常。"callee"属性对于arguments异质对象有更具体的含义,这些对象仅为某些类别的非严格函数创建。在普通变体中定义此属性是为了确保符合标准的ECMAScript实现不会以任何其他方式定义它。

注5

Arguments异质对象的ECMAScript实现历史上包含一个名为"caller"访问器属性。在ECMAScript 2017之前,本规范包括在普通arguments对象上定义抛出"caller"属性的定义。由于实现不再包含此扩展,ECMAScript 2017放弃了对抛出"caller"访问器的要求。

10.4.4.1 [[GetOwnProperty]] ( P )

Arguments异质对象 args[[GetOwnProperty]]内部方法接受参数P属性键),返回包含属性描述符undefined正常完成。调用时执行以下步骤:

  1. descOrdinaryGetOwnProperty(args, P)。
  2. 如果 descundefined,返回 undefined
  3. mapargs.[[ParameterMap]]
  4. isMapped 为 ! HasOwnProperty(map, P)。
  5. 如果 isMappedtrue,那么
    1. 设置 desc.[[Value]] 为 ! Get(map, P)。
  6. 返回 desc

10.4.4.2 [[DefineOwnProperty]] ( P, Desc )

Arguments异质对象 args[[DefineOwnProperty]]内部方法接受参数P属性键)和Desc属性描述符),返回包含布尔值的正常完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. newArgDescDesc
  4. 如果 isMappedtrueIsDataDescriptor(Desc) 为 true,那么
    1. 如果 Desc 没有 [[Value]] 字段,Desc[[Writable]] 字段,且 Desc.[[Writable]]false,那么
      1. 设置 newArgDescDesc 的副本。
      2. 设置 newArgDesc.[[Value]] 为 ! Get(map, P)。
  5. allowed 为 ! OrdinaryDefineOwnProperty(args, P, newArgDesc)。
  6. 如果 allowedfalse,返回 false
  7. 如果 isMappedtrue,那么
    1. 如果 IsAccessorDescriptor(Desc) 为 true,那么
      1. 执行 ! map.[[Delete]](P)。
    2. 否则,
      1. 如果 Desc[[Value]] 字段,那么
        1. 断言:以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
        2. 执行 ! Set(map, P, Desc.[[Value]], false)。
      2. 如果 Desc[[Writable]] 字段且 Desc.[[Writable]]false,那么
        1. 执行 ! map.[[Delete]](P)。
  8. 返回 true

10.4.4.3 [[Get]] ( P, Receiver )

Arguments异质对象 args[[Get]]内部方法接受参数P属性键)和ReceiverECMAScript语言值),返回包含ECMAScript语言值正常完成抛出完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. 如果 isMappedfalse,那么
    1. 返回 ? OrdinaryGet(args, P, Receiver)。
  4. 否则,
    1. 断言map 包含 P 的形式参数映射。
    2. 返回 ! Get(map, P)。

10.4.4.4 [[Set]] ( P, V, Receiver )

Arguments异质对象 args[[Set]]内部方法接受参数P属性键)、VECMAScript语言值)和ReceiverECMAScript语言值),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. 如果 SameValue(args, Receiver) 为 false,那么
    1. isMappedfalse
  2. 否则,
    1. mapargs.[[ParameterMap]]
    2. isMapped 为 ! HasOwnProperty(map, P)。
  3. 如果 isMappedtrue,那么
    1. 断言:以下Set将成功,因为由arguments对象映射的形式参数总是可写的。
    2. 执行 ! Set(map, P, V, false)。
  4. 返回 ? OrdinarySet(args, P, V, Receiver)。

10.4.4.5 [[Delete]] ( P )

Arguments异质对象 args[[Delete]]内部方法接受参数P属性键),返回包含布尔值的正常完成抛出完成。调用时执行以下步骤:

  1. mapargs.[[ParameterMap]]
  2. isMapped 为 ! HasOwnProperty(map, P)。
  3. result 为 ? OrdinaryDelete(args, P)。
  4. 如果 resulttrueisMappedtrue,那么
    1. 执行 ! map.[[Delete]](P)。
  5. 返回 result

10.4.4.6 CreateUnmappedArgumentsObject ( argumentsList )

抽象操作CreateUnmappedArgumentsObject接受参数argumentsListECMAScript语言值列表),返回普通对象。调用时执行以下步骤:

  1. lenargumentsList 中元素的数量。
  2. objOrdinaryObjectCreate(%Object.prototype%, « [[ParameterMap]] »)。
  3. 设置 obj.[[ParameterMap]]undefined
  4. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  5. index 为 0。
  6. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    3. 设置 indexindex + 1。
  7. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  8. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Get]]: %ThrowTypeError%, [[Set]]: %ThrowTypeError%, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 obj

10.4.4.7 CreateMappedArgumentsObject ( func, formals, argumentsList, env )

抽象操作CreateMappedArgumentsObject接受参数func(对象)、formals解析节点)、argumentsListECMAScript语言值列表)和env环境记录),返回arguments异质对象。调用时执行以下步骤:

  1. 断言formals 不包含剩余参数、任何绑定模式或任何初始化器。它可能包含重复标识符。
  2. lenargumentsList 中元素的数量。
  3. objMakeBasicObject[[Prototype]], [[Extensible]], [[ParameterMap]] »)。
  4. 按照10.4.4.1中指定的设置 obj.[[GetOwnProperty]]
  5. 按照10.4.4.2中指定的设置 obj.[[DefineOwnProperty]]
  6. 按照10.4.4.3中指定的设置 obj.[[Get]]
  7. 按照10.4.4.4中指定的设置 obj.[[Set]]
  8. 按照10.4.4.5中指定的设置 obj.[[Delete]]
  9. 设置 obj.[[Prototype]]%Object.prototype%
  10. mapOrdinaryObjectCreate(null)。
  11. 设置 obj.[[ParameterMap]]map
  12. parameterNamesformalsBoundNames
  13. numberOfParametersparameterNames 中元素的数量。
  14. index 为 0。
  15. 重复,当 index < len 时,
    1. valargumentsList[index]。
    2. 执行 ! CreateDataPropertyOrThrow(obj, ! ToString(𝔽(index)), val)。
    3. 设置 indexindex + 1。
  16. 执行 ! DefinePropertyOrThrow(obj, "length", PropertyDescriptor { [[Value]]: 𝔽(len), [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  17. mappedNames 为新的空列表
  18. 设置 indexnumberOfParameters - 1。
  19. 重复,当 index ≥ 0 时,
    1. nameparameterNames[index]。
    2. 如果 mappedNames 不包含 name,那么
      1. name 追加到 mappedNames
      2. 如果 index < len,那么
        1. gMakeArgGetter(name, env)。
        2. pMakeArgSetter(name, env)。
        3. 执行 ! map.[[DefineOwnProperty]](! ToString(𝔽(index)), PropertyDescriptor { [[Set]]: p, [[Get]]: g, [[Enumerable]]: false, [[Configurable]]: true })。
    3. 设置 indexindex - 1。
  20. 执行 ! DefinePropertyOrThrow(obj, %Symbol.iterator%, PropertyDescriptor { [[Value]]: %Array.prototype.values%, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  21. 执行 ! DefinePropertyOrThrow(obj, "callee", PropertyDescriptor { [[Value]]: func, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true })。
  22. 返回 obj

10.4.4.7.1 MakeArgGetter ( name, env )

抽象操作MakeArgGetter接受参数name(字符串)和env环境记录),返回函数对象。它创建一个内置函数对象,执行时返回在env中为name绑定的值。调用时执行以下步骤:

  1. getterClosure 为新的抽象闭包,没有参数,捕获nameenv,调用时执行以下步骤:
    1. 返回 env.GetBindingValue(name, false)。
  2. getterCreateBuiltinFunction(getterClosure, 0, "", « »)。
  3. 注:getter 从不直接被ECMAScript代码访问。
  4. 返回 getter

10.4.4.7.2 MakeArgSetter ( name, env )

抽象操作MakeArgSetter接受参数name(字符串)和env环境记录),返回函数对象。它创建一个内置函数对象,执行时在env中为name设置绑定的值。调用时执行以下步骤:

  1. setterClosure 为新的抽象闭包,参数为(value),捕获nameenv,调用时执行以下步骤:
    1. 返回 ! env.SetMutableBinding(name, value, false)。
  2. setterCreateBuiltinFunction(setterClosure, 1, "", « »)。
  3. 注:setter 从不直接被ECMAScript代码访问。
  4. 返回 setter

10.4.5 TypedArray 异质对象

TypedArray 是一个 异质对象,它对作为 规范数字字符串属性键 执行特殊处理,使用界内的 整数索引 子集来索引统一类型的元素,并强制执行其余部分不存在且不引起原型链遍历的不变性。

因为对于任何数字 nToString(n) 都是一个 规范数字字符串,实现可以将数字视为 属性键 用于 TypedArrays,而无需实际执行字符串转换。

TypedArrays 除了与 普通对象 相同的内部插槽外,还有 [[ViewedArrayBuffer]][[ArrayLength]][[ByteOffset]][[ContentType]][[TypedArrayName]] 内部插槽。

如果一个对象的 [[PreventExtensions]][[GetOwnProperty]][[HasProperty]][[DefineOwnProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其他基本内部方法使用 10.1 中找到的定义,则该对象是一个 TypedArray。这些方法由 TypedArrayCreate 安装。

10.4.5.1 [[PreventExtensions]] ( )

TypedArray O[[PreventExtensions]] 内部方法不接受参数并返回一个 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 注:6.1.7.3 中指定的可扩展性相关的不变性不允许此方法在 O 可以获得(或失去然后重新获得)属性时返回 true,这可能发生在当其底层缓冲区被调整大小时具有 整数索引 名称的属性上。
  2. 如果 IsTypedArrayFixedLength(O) 是 false,返回 false
  3. 返回 OrdinaryPreventExtensions(O)。

10.4.5.2 [[GetOwnProperty]] ( P )

TypedArray O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回一个 包含 属性描述符undefined 的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. valueTypedArrayGetElement(O, numericIndex)。
      2. 如果 valueundefined,返回 undefined
      3. 返回属性描述符 { [[Value]]: value[[Writable]]: true[[Enumerable]]: true[[Configurable]]: true }。
  2. 返回 OrdinaryGetOwnProperty(O, P)。

10.4.5.3 [[HasProperty]] ( P )

TypedArray O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,返回 IsValidIntegerIndex(O, numericIndex)。
  2. 返回 ? OrdinaryHasProperty(O, P)。

10.4.5.4 [[DefineOwnProperty]] ( P, Desc )

TypedArray O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 false
      2. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]false,返回 false
      3. 如果 Desc 有一个 [[Enumerable]] 字段且 Desc.[[Enumerable]]false,返回 false
      4. 如果 IsAccessorDescriptor(Desc) 是 true,返回 false
      5. 如果 Desc 有一个 [[Writable]] 字段 且 Desc.[[Writable]]false,返回 false
      6. 如果 Desc 有一个 [[Value]] 字段, 执行 ? TypedArraySetElement(O, numericIndex, Desc.[[Value]])。
      7. 返回 true
  2. 返回 ! OrdinaryDefineOwnProperty(O, P, Desc)。

10.4.5.5 [[Get]] ( P, Receiver )

TypedArray O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 返回 TypedArrayGetElement(O, numericIndex)。
  2. 返回 ? OrdinaryGet(O, P, Receiver)。

10.4.5.6 [[Set]] ( P, V, Receiver )

TypedArray O[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 SameValue(O, Receiver) 是 true,那么
        1. 执行 ? TypedArraySetElement(O, numericIndex, V)。
        2. 返回 true
      2. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 true
  2. 返回 ? OrdinarySet(O, P, V, Receiver)。

10.4.5.7 [[Delete]] ( P )

TypedArray O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个字符串,那么
    1. numericIndexCanonicalNumericIndexString(P)。
    2. 如果 numericIndex 不是 undefined,那么
      1. 如果 IsValidIntegerIndex(O, numericIndex) 是 false,返回 true;否则返回 false
  2. 返回 ! OrdinaryDelete(O, P)。

10.4.5.8 [[OwnPropertyKeys]] ( )

TypedArray O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键列表 的正常完成。它在被调用时执行以下步骤:

  1. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  2. keys 为一个新的空 列表
  3. 如果 IsTypedArrayOutOfBounds(taRecord) 是 false,那么
    1. lengthTypedArrayLength(taRecord)。
    2. 对于每个满足 0 ≤ i < length整数 i,按升序,执行
      1. 将 ! ToString(𝔽(i)) 追加到 keys
  4. 对于 O 的每个自己的 属性键 P,使得 P 是一个字符串P 不是一个 整数索引,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  5. 对于 O 的每个自己的 属性键 P,使得 P 是一个符号,按属性创建的升序时间顺序,执行
    1. P 追加到 keys
  6. 返回 keys

10.4.5.9 TypedArray 带缓冲区见证记录

TypedArray 带缓冲区见证记录 是一个用于封装 TypedArray 以及所查看缓冲区的缓存字节长度的 记录 值。当所查看的缓冲区是 可增长的 SharedArrayBuffer 时,它用于帮助确保字节长度数据块的单个共享内存读取事件。

TypedArray 带缓冲区见证记录具有 表 32 中列出的字段。

表 32:TypedArray 带缓冲区见证记录 字段
字段名称 含义
[[Object]] 一个 TypedArray 其缓冲区字节长度被加载的 TypedArray
[[CachedBufferByteLength]] 一个非负 整数detached 创建 记录 时对象的 [[ViewedArrayBuffer]] 的字节长度。

10.4.5.10 MakeTypedArrayWithBufferWitnessRecord ( obj, order )

抽象操作 MakeTypedArrayWithBufferWitnessRecord 接受参数 obj(一个 TypedArray)和 orderseq-cstunordered)并返回一个 TypedArray 带缓冲区见证记录。它在被调用时执行以下步骤:

  1. bufferobj.[[ViewedArrayBuffer]]
  2. 如果 IsDetachedBuffer(buffer) 是 true,那么
    1. byteLengthdetached
  3. 否则,
    1. byteLengthArrayBufferByteLength(buffer, order)。
  4. 返回 TypedArray 带缓冲区见证记录 { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }。

10.4.5.11 TypedArrayCreate ( prototype )

抽象操作 TypedArrayCreate 接受参数 prototype(一个对象)并返回一个 TypedArray。它用于指定新 TypedArrays 的创建。它在被调用时执行以下步骤:

  1. internalSlotsList 为 « [[Prototype]][[Extensible]][[ViewedArrayBuffer]][[TypedArrayName]][[ContentType]][[ByteLength]][[ByteOffset]][[ArrayLength]] »。
  2. AMakeBasicObject(internalSlotsList)。
  3. 设置 A.[[PreventExtensions]]10.4.5.1 中所指定。
  4. 设置 A.[[GetOwnProperty]]10.4.5.2 中所指定。
  5. 设置 A.[[HasProperty]]10.4.5.3 中所指定。
  6. 设置 A.[[DefineOwnProperty]]10.4.5.4 中所指定。
  7. 设置 A.[[Get]]10.4.5.5 中所指定。
  8. 设置 A.[[Set]]10.4.5.6 中所指定。
  9. 设置 A.[[Delete]]10.4.5.7 中所指定。
  10. 设置 A.[[OwnPropertyKeys]]10.4.5.8 中所指定。
  11. 设置 A.[[Prototype]]prototype
  12. 返回 A

10.4.5.12 TypedArrayByteLength ( taRecord )

抽象操作 TypedArrayByteLength 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个非负 整数。它在被调用时执行以下步骤:

  1. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 0。
  2. lengthTypedArrayLength(taRecord)。
  3. 如果 length = 0,返回 0。
  4. OtaRecord.[[Object]]
  5. 如果 O.[[ByteLength]] 不是 auto,返回 O.[[ByteLength]]
  6. elementSizeTypedArrayElementSize(O)。
  7. 返回 length × elementSize

10.4.5.13 TypedArrayLength ( taRecord )

抽象操作 TypedArrayLength 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个非负 整数。它在被调用时执行以下步骤:

  1. 断言IsTypedArrayOutOfBounds(taRecord) 是 false
  2. OtaRecord.[[Object]]
  3. 如果 O.[[ArrayLength]] 不是 auto,返回 O.[[ArrayLength]]
  4. 断言IsFixedLengthArrayBuffer(O.[[ViewedArrayBuffer]]) 是 false
  5. byteOffsetO.[[ByteOffset]]
  6. elementSizeTypedArrayElementSize(O)。
  7. byteLengthtaRecord.[[CachedBufferByteLength]]
  8. 断言byteLength 不是 detached
  9. 返回 floor((byteLength - byteOffset) / elementSize)。

10.4.5.14 IsTypedArrayOutOfBounds ( taRecord )

抽象操作 IsTypedArrayOutOfBounds 接受参数 taRecord(一个 TypedArray 带缓冲区见证记录)并返回一个布尔值。它检查对象的任何数字属性是否引用了在底层缓冲区边界内不包含的索引处的值。它在被调用时执行以下步骤:

  1. OtaRecord.[[Object]]
  2. bufferByteLengthtaRecord.[[CachedBufferByteLength]]
  3. 断言IsDetachedBuffer(O.[[ViewedArrayBuffer]]) 是 true 当且仅当 bufferByteLengthdetached
  4. 如果 bufferByteLengthdetached,返回 true
  5. byteOffsetStartO.[[ByteOffset]]
  6. 如果 O.[[ArrayLength]]auto,那么
    1. byteOffsetEndbufferByteLength
  7. 否则,
    1. elementSizeTypedArrayElementSize(O)。
    2. byteOffsetEndbyteOffsetStart + O.[[ArrayLength]] × elementSize
  8. 如果 byteOffsetStart > bufferByteLengthbyteOffsetEnd > bufferByteLength,返回 true
  9. 注:0长度的 TypedArrays 不被认为是越界的。
  10. 返回 false

10.4.5.15 IsTypedArrayFixedLength ( O )

抽象操作 IsTypedArrayFixedLength 接受参数 O(一个 TypedArray)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 O.[[ArrayLength]]auto,返回 false
  2. bufferO.[[ViewedArrayBuffer]]
  3. 如果 IsFixedLengthArrayBuffer(buffer) 是 falseIsSharedArrayBuffer(buffer) 是 false,返回 false
  4. 返回 true

10.4.5.16 IsValidIntegerIndex ( O, index )

抽象操作 IsValidIntegerIndex 接受参数 O(一个 TypedArray)和 index(一个数字)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 IsDetachedBuffer(O.[[ViewedArrayBuffer]]) 是 true,返回 false
  2. 如果 index 不是一个 整数数字,返回 false
  3. 如果 index-0𝔽index < -0𝔽,返回 false
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, unordered)。
  5. 注:当 O 的支持缓冲区是 可增长的 SharedArrayBuffer 时,边界检查不是同步操作。
  6. 如果 IsTypedArrayOutOfBounds(taRecord) 是 true,返回 false
  7. lengthTypedArrayLength(taRecord)。
  8. 如果 (index) ≥ length,返回 false
  9. 返回 true

10.4.5.17 TypedArrayGetElement ( O, index )

抽象操作 TypedArrayGetElement 接受参数 O(一个 TypedArray)和 index(一个数字)并返回一个数字、一个 BigInt 或 undefined。它在被调用时执行以下步骤:

  1. 如果 IsValidIntegerIndex(O, index) 是 false,返回 undefined
  2. offsetO.[[ByteOffset]]
  3. elementSizeTypedArrayElementSize(O)。
  4. byteIndexInBuffer 为 ((index) × elementSize) + offset
  5. elementTypeTypedArrayElementType(O)。
  6. 返回 GetValueFromBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, true, unordered)。

10.4.5.18 TypedArraySetElement ( O, index, value )

抽象操作 TypedArraySetElement 接受参数 O(一个 TypedArray)、index(一个数字)和 value(一个 ECMAScript 语言值)并返回 包含 unused 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 O.[[ContentType]]bigint,让 numValue 为 ? ToBigInt(value)。
  2. 否则,让 numValue 为 ? ToNumber(value)。
  3. 如果 IsValidIntegerIndex(O, index) 是 true,那么
    1. offsetO.[[ByteOffset]]
    2. elementSizeTypedArrayElementSize(O)。
    3. byteIndexInBuffer 为 ((index) × elementSize) + offset
    4. elementTypeTypedArrayElementType(O)。
    5. 执行 SetValueInBuffer(O.[[ViewedArrayBuffer]], byteIndexInBuffer, elementType, numValue, true, unordered)。
  4. 返回 unused

此操作总是显得成功,但是当尝试写入 TypedArray 的末尾之外或写入由分离的 ArrayBuffer 支持的 TypedArray 时,它没有效果。

10.4.5.19 IsArrayBufferViewOutOfBounds ( O )

抽象操作 IsArrayBufferViewOutOfBounds 接受参数 O(一个 TypedArray 或一个 DataView)并返回一个布尔值。它检查 TypedArray 的任何数字属性或 DataView 对象的方法是否可以引用在底层数据块边界内不包含的索引处的值。此抽象操作作为上游规范的便利而存在。它在被调用时执行以下步骤:

  1. 如果 O 有一个 [[DataView]] 内部插槽,那么
    1. viewRecordMakeDataViewWithBufferWitnessRecord(O, seq-cst)。
    2. 返回 IsViewOutOfBounds(viewRecord)。
  2. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  3. 返回 IsTypedArrayOutOfBounds(taRecord)。

10.4.6 模块命名空间异质对象

模块命名空间异质对象 是一个 异质对象,它暴露从 ECMAScript 模块 导出的绑定(参见 16.2.3)。模块命名空间异质对象 的字符串键自己的属性与 模块 导出的绑定名称之间存在一对一的对应关系。导出的绑定包括使用 export * 导出项间接导出的任何绑定。每个字符串值自己的 属性键 是对应导出绑定名称的 StringValue。这些是 模块命名空间异质对象 的唯一字符串键属性。每个这样的属性都具有属性 { [[Writable]]: true[[Enumerable]]: true[[Configurable]]: false }。模块命名空间异质对象 是不可扩展的。

如果一个对象的 [[GetPrototypeOf]][[SetPrototypeOf]][[IsExtensible]][[PreventExtensions]][[GetOwnProperty]][[DefineOwnProperty]][[HasProperty]][[Get]][[Set]][[Delete]][[OwnPropertyKeys]] 内部方法使用本节中的定义,并且其他基本内部方法使用 10.1 中找到的定义,则该对象是一个 模块命名空间异质对象。这些方法由 ModuleNamespaceCreate 安装。

模块命名空间异质对象 具有 表 33 中定义的内部插槽。

表 33:模块命名空间异质对象的内部插槽
内部插槽 类型 描述
[[Module]] 一个 模块记录 此命名空间暴露其导出的 模块记录
[[Exports]] 一个字符串的 列表 一个 列表,其元素是作为此对象自己的属性暴露的导出名称的字符串值。该列表按 字典代码单元顺序 排序。

10.4.6.1 [[GetPrototypeOf]] ( )

模块命名空间异质对象[[GetPrototypeOf]] 内部方法不接受参数并返回 包含 null 的正常完成。它在被调用时执行以下步骤:

  1. 返回 null

10.4.6.2 [[SetPrototypeOf]] ( V )

模块命名空间异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 返回 ! SetImmutablePrototype(O, V)。

10.4.6.3 [[IsExtensible]] ( )

模块命名空间异质对象[[IsExtensible]] 内部方法不接受参数并返回 包含 false 的正常完成。它在被调用时执行以下步骤:

  1. 返回 false

10.4.6.4 [[PreventExtensions]] ( )

模块命名空间异质对象[[PreventExtensions]] 内部方法不接受参数并返回 包含 true 的正常完成。它在被调用时执行以下步骤:

  1. 返回 true

10.4.6.5 [[GetOwnProperty]] ( P )

模块命名空间异质对象 O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 属性描述符undefined 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 OrdinaryGetOwnProperty(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 不包含 P,返回 undefined
  4. value 为 ? O.[[Get]](P, O)。
  5. 返回属性描述符 { [[Value]]: value[[Writable]]: true[[Enumerable]]: true[[Configurable]]: false }。

10.4.6.6 [[DefineOwnProperty]] ( P, Desc )

模块命名空间异质对象 O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 ! OrdinaryDefineOwnProperty(O, P, Desc)。
  2. current 为 ? O.[[GetOwnProperty]](P)。
  3. 如果 currentundefined,返回 false
  4. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]true,返回 false
  5. 如果 Desc 有一个 [[Enumerable]] 字段且 Desc.[[Enumerable]]false,返回 false
  6. 如果 IsAccessorDescriptor(Desc) 是 true,返回 false
  7. 如果 Desc 有一个 [[Writable]] 字段且 Desc.[[Writable]]false,返回 false
  8. 如果 Desc 有一个 [[Value]] 字段,返回 SameValue(Desc.[[Value]], current.[[Value]])。
  9. 返回 true

10.4.6.7 [[HasProperty]] ( P )

模块命名空间异质对象 O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,返回 ! OrdinaryHasProperty(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 包含 P,返回 true
  4. 返回 false

10.4.6.8 [[Get]] ( P, Receiver )

模块命名空间异质对象 O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,那么
    1. 返回 ! OrdinaryGet(O, P, Receiver)。
  2. exportsO.[[Exports]]
  3. 如果 exports 不包含 P,返回 undefined
  4. mO.[[Module]]
  5. bindingm.ResolveExport(P)。
  6. 断言binding 是一个 ResolvedBinding 记录
  7. targetModulebinding.[[Module]]
  8. 断言targetModule 不是 undefined
  9. 如果 binding.[[BindingName]]namespace,那么
    1. 返回 GetModuleNamespace(targetModule)。
  10. targetEnvtargetModule.[[Environment]]
  11. 如果 targetEnvempty,抛出一个 ReferenceError 异常。
  12. 返回 ? targetEnv.GetBindingValue(binding.[[BindingName]], true)。

ResolveExport 是无副作用的。每当使用特定的 exportNameresolveSet 对作为参数调用此操作时,它必须返回相同的结果。实现可能选择预计算或缓存每个 模块命名空间异质对象[[Exports]] 的 ResolveExport 结果。

10.4.6.9 [[Set]] ( P, V, Receiver )

模块命名空间异质对象[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 false 的正常完成。它在被调用时执行以下步骤:

  1. 返回 false

10.4.6.10 [[Delete]] ( P )

模块命名空间异质对象 O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成。它在被调用时执行以下步骤:

  1. 如果 P 是一个符号,那么
    1. 返回 ! OrdinaryDelete(O, P)。
  2. exportsO.[[Exports]]
  3. 如果 exports 包含 P,返回 false
  4. 返回 true

10.4.6.11 [[OwnPropertyKeys]] ( )

模块命名空间异质对象 O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 属性键列表 的正常完成。它在被调用时执行以下步骤:

  1. exportsO.[[Exports]]
  2. symbolKeysOrdinaryOwnPropertyKeys(O)。
  3. 返回 exportssymbolKeys列表连接

10.4.6.12 ModuleNamespaceCreate ( module, exports )

抽象操作 ModuleNamespaceCreate 接受参数 module(一个 模块记录)和 exports(一个字符串的 列表)并返回一个 模块命名空间异质对象。它用于指定新 模块命名空间异质对象 的创建。它在被调用时执行以下步骤:

  1. 断言module.[[Namespace]]empty
  2. internalSlotsList表 33 中列出的内部插槽。
  3. MMakeBasicObject(internalSlotsList)。
  4. 设置 M 的基本内部方法为 10.4.6 中指定的定义。
  5. 设置 M.[[Module]]module
  6. sortedExports 为一个 列表,其元素是 exports 的元素,按 字典代码单元顺序 排序。
  7. 设置 M.[[Exports]]sortedExports
  8. 创建 M 的自己的属性,对应于 28.3 中的定义。
  9. 设置 module.[[Namespace]]M
  10. 返回 M

10.4.7 不可变原型异质对象

不可变原型异质对象 是一个 异质对象,它具有一个 [[Prototype]] 内部插槽,一旦初始化后就不会更改。

如果一个对象的 [[SetPrototypeOf]] 内部方法使用以下实现,则该对象是一个 不可变原型异质对象。(其他基本内部方法可以使用任何实现,取决于所涉及的特定 不可变原型异质对象。)

与其他 异质对象 不同,没有为 不可变原型异质对象 提供专门的创建抽象操作。这是因为它们仅被 %Object.prototype%宿主环境 使用,而在 宿主环境 中,相关对象可能在其他方面也是异质的,因此需要它们自己的专门创建操作。

10.4.7.1 [[SetPrototypeOf]] ( V )

不可变原型异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 返回 ? SetImmutablePrototype(O, V)。

10.4.7.2 SetImmutablePrototype ( O, V )

抽象操作 SetImmutablePrototype 接受参数 O(一个对象)和 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. current 为 ? O.[[GetPrototypeOf]]()。
  2. 如果 SameValue(V, current) 是 true,返回 true
  3. 返回 false

10.5 代理对象内部方法和内部插槽

代理对象是一个 异质对象,其基本内部方法部分使用 ECMAScript 代码实现。每个代理对象都有一个名为 [[ProxyHandler]] 的内部插槽。[[ProxyHandler]] 的值是一个对象,称为代理的处理器对象,或者是 null。处理器对象的方法(参见 表 34)可用于增强代理对象一个或多个内部方法的实现。每个代理对象还有一个名为 [[ProxyTarget]] 的内部插槽,其值要么是一个对象,要么是 null。这个对象称为代理的目标对象

如果一个对象的基本内部方法(包括 [[Call]][[Construct]],如果适用)使用本节中的定义,则该对象是一个 代理异质对象。这些内部方法在 ProxyCreate 中安装。

表 34:代理处理器方法
内部方法 处理器方法
[[GetPrototypeOf]] getPrototypeOf
[[SetPrototypeOf]] setPrototypeOf
[[IsExtensible]] isExtensible
[[PreventExtensions]] preventExtensions
[[GetOwnProperty]] getOwnPropertyDescriptor
[[DefineOwnProperty]] defineProperty
[[HasProperty]] has
[[Get]] get
[[Set]] set
[[Delete]] deleteProperty
[[OwnPropertyKeys]] ownKeys
[[Call]] apply
[[Construct]] construct

当调用处理器方法来提供代理对象内部方法的实现时,处理器方法将代理的目标对象作为参数传递。代理的处理器对象不一定具有与每个基本内部方法相对应的方法。如果处理器对象没有与内部陷阱相对应的方法,则在代理上调用内部方法会导致在代理的目标对象上调用相应的内部方法。

代理对象的 [[ProxyHandler]][[ProxyTarget]] 内部插槽在创建对象时总是被初始化,通常不能被修改。某些代理对象以允许它们随后被撤销的方式创建。当代理被撤销时,其 [[ProxyHandler]][[ProxyTarget]] 内部插槽被设置为 null,导致该代理对象上内部方法的后续调用抛出 TypeError 异常。

因为代理对象允许通过任意 ECMAScript 代码提供内部方法的实现,所以可以定义一个代理对象,其处理器方法违反了 6.1.7.3 中定义的不变量。6.1.7.3 中定义的一些内部方法不变量是基本的完整性不变量。这些不变量由本节中指定的代理对象内部方法显式强制执行。ECMAScript 实现必须在所有可能的不变量违反的情况下保持健壮。

在以下算法描述中,假设 O 是一个 ECMAScript 代理对象,P 是一个 属性键 值,V 是任何 ECMAScript 语言值Desc 是一个 属性描述符 记录。

10.5.1 [[GetPrototypeOf]] ( )

代理异质对象 O[[GetPrototypeOf]] 内部方法不接受参数并返回 包含 对象或 null 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "getPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetPrototypeOf]]()。
  7. handlerProto 为 ? Call(trap, handler, « target »)。
  8. 如果 handlerProto 不是一个对象handlerProto 不是 null,抛出一个 TypeError 异常。
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 handlerProto
  11. targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(handlerProto, targetProto) 是 false,抛出一个 TypeError 异常。
  13. 返回 handlerProto

代理对象的 [[GetPrototypeOf]] 强制执行以下不变量:

  • [[GetPrototypeOf]] 的结果必须是一个对象或 null
  • 如果目标对象不可扩展,应用于代理对象的 [[GetPrototypeOf]] 必须返回与应用于代理对象的目标对象的 [[GetPrototypeOf]] 相同的值。

10.5.2 [[SetPrototypeOf]] ( V )

代理异质对象 O[[SetPrototypeOf]] 内部方法接受参数 V(一个对象或 null)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "setPrototypeOf")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[SetPrototypeOf]](V)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, V »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. extensibleTarget 为 ? IsExtensible(target)。
  10. 如果 extensibleTargettrue,返回 true
  11. targetProto 为 ? target.[[GetPrototypeOf]]()。
  12. 如果 SameValue(V, targetProto) 是 false,抛出一个 TypeError 异常。
  13. 返回 true

代理对象的 [[SetPrototypeOf]] 强制执行以下不变量:

  • [[SetPrototypeOf]] 的结果 是一个布尔值
  • 如果目标对象不可扩展,参数值必须与应用于目标对象的 [[GetPrototypeOf]] 的结果相同。

10.5.3 [[IsExtensible]] ( )

代理异质对象 O[[IsExtensible]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "isExtensible")。
  6. 如果 trapundefined,那么
    1. 返回 ? IsExtensible(target)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. targetResult 为 ? IsExtensible(target)。
  9. 如果 booleanTrapResult 不是 targetResult,抛出一个 TypeError 异常。
  10. 返回 booleanTrapResult

代理对象的 [[IsExtensible]] 强制执行以下不变量:

  • [[IsExtensible]] 的结果 是一个布尔值
  • 应用于代理对象的 [[IsExtensible]] 必须返回与应用于代理对象的目标对象的 [[IsExtensible]] 相同的值。

10.5.4 [[PreventExtensions]] ( )

代理异质对象 O[[PreventExtensions]] 内部方法不接受参数并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "preventExtensions")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[PreventExtensions]]()
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target »))。
  8. 如果 booleanTrapResulttrue,那么
    1. extensibleTarget 为 ? IsExtensible(target)。
    2. 如果 extensibleTargettrue,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult

代理对象的 [[PreventExtensions]] 强制执行以下不变量:

  • [[PreventExtensions]] 的结果 是一个布尔值
  • 应用于代理对象的 [[PreventExtensions]] 仅在应用于代理对象的目标对象的 [[IsExtensible]]false 时才返回 true

10.5.5 [[GetOwnProperty]] ( P )

代理异质对象 O[[GetOwnProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 属性描述符undefined 的正常完成,或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "getOwnPropertyDescriptor")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[GetOwnProperty]](P)。
  7. trapResultObj 为 ? Call(trap, handler, « target, P »)。
  8. 如果 trapResultObj 不是一个对象trapResultObj 不是 undefined,抛出一个 TypeError 异常。
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  10. 如果 trapResultObjundefined,那么
    1. 如果 targetDescundefined,返回 undefined
    2. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
    3. extensibleTarget 为 ? IsExtensible(target)。
    4. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    5. 返回 undefined
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. resultDesc 为 ? ToPropertyDescriptor(trapResultObj)。
  13. 执行 CompletePropertyDescriptor(resultDesc)。
  14. validIsCompatiblePropertyDescriptor(extensibleTarget, resultDesc, targetDesc)。
  15. 如果 validfalse,抛出一个 TypeError 异常。
  16. 如果 resultDesc.[[Configurable]]false,那么
    1. 如果 targetDescundefinedtargetDesc.[[Configurable]]true,那么
      1. 抛出一个 TypeError 异常。
    2. 如果 resultDesc 有一个 [[Writable]] 字段且 resultDesc.[[Writable]]false,那么
      1. 断言targetDesc 有一个 [[Writable]] 字段。
      2. 如果 targetDesc.[[Writable]]true,抛出一个 TypeError 异常。
  17. 返回 resultDesc

代理对象的 [[GetOwnProperty]] 强制执行以下不变量:

  • [[GetOwnProperty]] 的结果必须是一个对象或 undefined
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为不可扩展目标对象的自有属性存在,则不能报告该属性不存在。
  • 如果属性不作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性存在。
  • 除非属性作为目标对象的不可配置自有属性存在,否则不能报告该属性为不可配置。
  • 除非属性作为目标对象的不可配置、不可写自有属性存在,否则不能报告该属性既不可配置又不可写。

10.5.6 [[DefineOwnProperty]] ( P, Desc )

代理异质对象 O[[DefineOwnProperty]] 内部方法接受参数 P(一个 属性键)和 Desc(一个 属性描述符)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "defineProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[DefineOwnProperty]](P, Desc)。
  7. descObjFromPropertyDescriptor(Desc)。
  8. booleanTrapResultToBoolean(? Call(trap, handler, « target, P, descObj »))。
  9. 如果 booleanTrapResultfalse,返回 false
  10. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  11. extensibleTarget 为 ? IsExtensible(target)。
  12. 如果 Desc 有一个 [[Configurable]] 字段且 Desc.[[Configurable]]false,那么
    1. settingConfigFalsetrue
  13. 否则,
    1. settingConfigFalsefalse
  14. 如果 targetDescundefined,那么
    1. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetrue,抛出一个 TypeError 异常。
  15. 否则,
    1. 如果 IsCompatiblePropertyDescriptor(extensibleTarget, Desc, targetDesc) 是 false,抛出一个 TypeError 异常。
    2. 如果 settingConfigFalsetruetargetDesc.[[Configurable]]true,抛出一个 TypeError 异常。
    3. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Configurable]]false,且 targetDesc.[[Writable]]true,那么
      1. 如果 Desc 有一个 [[Writable]] 字段且 Desc.[[Writable]]false,抛出一个 TypeError 异常。
  16. 返回 true

代理对象的 [[DefineOwnProperty]] 强制执行以下不变量:

  • [[DefineOwnProperty]] 的结果 是一个布尔值
  • 如果目标对象不可扩展,则不能添加属性。
  • 除非目标对象存在相应的不可配置自有属性,否则属性不能为不可配置。
  • 除非目标对象存在相应的不可配置、不可写自有属性,否则不可配置属性不能为不可写。
  • 如果属性有相应的目标对象属性,则使用 [[DefineOwnProperty]] 将该属性的 属性描述符 应用于目标对象不会抛出异常。

10.5.7 [[HasProperty]] ( P )

代理异质对象 O[[HasProperty]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "has")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[HasProperty]](P)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P »))。
  8. 如果 booleanTrapResultfalse,那么
    1. targetDesc 为 ? target.[[GetOwnProperty]](P)。
    2. 如果 targetDesc 不是 undefined,那么
      1. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
      2. extensibleTarget 为 ? IsExtensible(target)。
      3. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  9. 返回 booleanTrapResult

代理对象的 [[HasProperty]] 强制执行以下不变量:

  • [[HasProperty]] 的结果 是一个布尔值
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性不存在。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性不存在。

10.5.8 [[Get]] ( P, Receiver )

代理异质对象 O[[Get]] 内部方法接受参数 P(一个 属性键)和 Receiver(一个 ECMAScript 语言值)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "get")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Get]](P, Receiver)。
  7. trapResult 为 ? Call(trap, handler, « target, P, Receiver »)。
  8. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  9. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(trapResult, targetDesc.[[Value]]) 是 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 truetargetDesc.[[Get]]undefined,那么
      1. 如果 trapResult 不是 undefined,抛出一个 TypeError 异常。
  10. 返回 trapResult

代理对象的 [[Get]] 强制执行以下不变量:

  • 如果目标对象属性是不可写、不可配置的自有 数据属性,则为属性报告的值必须与相应目标对象属性的值相同。
  • 如果相应的目标对象属性是不可配置的自有 访问器属性,且其 [[Get]] 特性为 undefined,则为属性报告的值必须是 undefined

10.5.9 [[Set]] ( P, V, Receiver )

代理异质对象 O[[Set]] 内部方法接受参数 P(一个 属性键)、V(一个 ECMAScript 语言值)和 Receiver(一个 ECMAScript 语言值)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "set")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Set]](P, V, Receiver)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P, V, Receiver »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  10. 如果 targetDesc 不是 undefinedtargetDesc.[[Configurable]]false,那么
    1. 如果 IsDataDescriptor(targetDesc) 是 truetargetDesc.[[Writable]]false,那么
      1. 如果 SameValue(V, targetDesc.[[Value]]) 是 false,抛出一个 TypeError 异常。
    2. 如果 IsAccessorDescriptor(targetDesc) 是 true,那么
      1. 如果 targetDesc.[[Set]]undefined,抛出一个 TypeError 异常。
  11. 返回 true

代理对象的 [[Set]] 强制执行以下不变量:

  • [[Set]] 的结果 是一个布尔值
  • 如果相应的目标对象属性是不可写、不可配置的自有 数据属性,则不能将属性的值更改为与相应目标对象属性的值不同。
  • 如果相应的目标对象属性是不可配置的自有 访问器属性,且其 [[Set]] 特性为 undefined,则不能设置属性的值。

10.5.10 [[Delete]] ( P )

代理异质对象 O[[Delete]] 内部方法接受参数 P(一个 属性键)并返回 包含 布尔值的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "deleteProperty")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[Delete]](P)。
  7. booleanTrapResultToBoolean(? Call(trap, handler, « target, P »))。
  8. 如果 booleanTrapResultfalse,返回 false
  9. targetDesc 为 ? target.[[GetOwnProperty]](P)。
  10. 如果 targetDescundefined,返回 true
  11. 如果 targetDesc.[[Configurable]]false,抛出一个 TypeError 异常。
  12. extensibleTarget 为 ? IsExtensible(target)。
  13. 如果 extensibleTargetfalse,抛出一个 TypeError 异常。
  14. 返回 true

代理对象的 [[Delete]] 强制执行以下不变量:

  • [[Delete]] 的结果 是一个布尔值
  • 如果属性作为目标对象的不可配置自有属性存在,则不能报告该属性被删除。
  • 如果属性作为目标对象的自有属性存在且目标对象不可扩展,则不能报告该属性被删除。

10.5.11 [[OwnPropertyKeys]] ( )

代理异质对象 O[[OwnPropertyKeys]] 内部方法不接受参数并返回 包含 列表 的正常完成(该列表包含 属性键)或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "ownKeys")。
  6. 如果 trapundefined,那么
    1. 返回 ? target.[[OwnPropertyKeys]]()
  7. trapResultArray 为 ? Call(trap, handler, « target »)。
  8. trapResult 为 ? CreateListFromArrayLike(trapResultArray, property-key)。
  9. 如果 trapResult 包含任何重复条目,抛出一个 TypeError 异常。
  10. extensibleTarget 为 ? IsExtensible(target)。
  11. targetKeys 为 ? target.[[OwnPropertyKeys]]()
  12. 断言targetKeys 是一个包含 属性键列表
  13. 断言targetKeys 不包含重复条目。
  14. targetConfigurableKeys 为一个新的空 列表
  15. targetNonconfigurableKeys 为一个新的空 列表
  16. targetKeys 的每个元素 key,执行
    1. desc 为 ? target.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefineddesc.[[Configurable]]false,那么
      1. key 追加到 targetNonconfigurableKeys
    3. 否则,
      1. key 追加到 targetConfigurableKeys
  17. 如果 extensibleTargettruetargetNonconfigurableKeys 是空的,那么
    1. 返回 trapResult
  18. uncheckedResultKeys 为一个 列表,其元素是 trapResult 的元素。
  19. targetNonconfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,抛出一个 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  20. 如果 extensibleTargettrue,返回 trapResult
  21. targetConfigurableKeys 的每个元素 key,执行
    1. 如果 uncheckedResultKeys 不包含 key,抛出一个 TypeError 异常。
    2. uncheckedResultKeys 中移除 key
  22. 如果 uncheckedResultKeys 不是空的,抛出一个 TypeError 异常。
  23. 返回 trapResult

代理对象的 [[OwnPropertyKeys]] 强制执行以下不变量:

  • [[OwnPropertyKeys]] 的结果是一个 列表
  • 返回的 列表 不包含重复条目。
  • 返回的 列表 的每个元素都是一个 属性键
  • 结果 列表 必须包含目标对象所有不可配置自有属性的键。
  • 如果目标对象不可扩展,则结果 列表 必须包含目标对象自有属性的所有键,且不包含其他值。

10.5.12 [[Call]] ( thisArgument, argumentsList )

代理异质对象 O[[Call]] 内部方法接受参数 thisArgument(一个 ECMAScript 语言值)和 argumentsList(一个包含 ECMAScript 语言值列表)并返回 包含 ECMAScript 语言值 的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. handlerO.[[ProxyHandler]]
  4. 断言handler 是一个对象
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,那么
    1. 返回 ? Call(target, thisArgument, argumentsList)。
  7. argArrayCreateArrayFromList(argumentsList)。
  8. 返回 ? Call(trap, handler, « target, thisArgument, argArray »)。

代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Call]] 内部方法的对象时,才具有 [[Call]] 内部方法。

10.5.13 [[Construct]] ( argumentsList, newTarget )

代理异质对象 O[[Construct]] 内部方法接受参数 argumentsList(一个包含 ECMAScript 语言值列表)和 newTarget(一个 构造函数)并返回 包含 对象的正常完成或 抛出完成。它在被调用时执行以下步骤:

  1. 执行 ? ValidateNonRevokedProxy(O)。
  2. targetO.[[ProxyTarget]]
  3. 断言IsConstructor(target) 是 true
  4. handlerO.[[ProxyHandler]]
  5. 断言handler 是一个对象
  6. trap 为 ? GetMethod(handler, "construct")。
  7. 如果 trapundefined,那么
    1. 返回 ? Construct(target, argumentsList, newTarget)。
  8. argArrayCreateArrayFromList(argumentsList)。
  9. newObj 为 ? Call(trap, handler, « target, argArray, newTarget »)。
  10. 如果 newObj 不是一个对象,抛出一个 TypeError 异常。
  11. 返回 newObj
注 1

代理异质对象 只有在其 [[ProxyTarget]] 内部插槽的初始值是具有 [[Construct]] 内部方法的对象时,才具有 [[Construct]] 内部方法。

注 2

代理对象的 [[Construct]] 强制执行以下不变量:

  • [[Construct]] 的结果必须是一个对象。

10.5.14 ValidateNonRevokedProxy ( proxy )

抽象操作 ValidateNonRevokedProxy 接受参数 proxy(一个 代理异质对象)并返回 包含 unused 的正常完成或 抛出完成。如果 proxy 已被撤销,它会抛出一个 TypeError 异常。它在被调用时执行以下步骤:

  1. 如果 proxy.[[ProxyTarget]]null,抛出一个 TypeError 异常。
  2. 断言proxy.[[ProxyHandler]] 不是 null
  3. 返回 unused

10.5.15 ProxyCreate ( target, handler )

抽象操作 ProxyCreate 接受参数 target(一个 ECMAScript 语言值)和 handler(一个 ECMAScript 语言值)并返回 包含 代理异质对象 的正常完成或 抛出完成。它用于指定新代理对象的创建。它在被调用时执行以下步骤:

  1. 如果 target 不是一个对象,抛出一个 TypeError 异常。
  2. 如果 handler 不是一个对象,抛出一个 TypeError 异常。
  3. PMakeBasicObject[[ProxyHandler]], [[ProxyTarget]] »)。
  4. P 的基本内部方法(除了 [[Call]][[Construct]])设置为 10.5 中指定的定义。
  5. 如果 IsCallable(target) 是 true,那么
    1. 按照 10.5.12 中的指定设置 P.[[Call]]
    2. 如果 IsConstructor(target) 是 true,那么
      1. 按照 10.5.13 中的指定设置 P.[[Construct]]
  6. 设置 P.[[ProxyTarget]]target
  7. 设置 P.[[ProxyHandler]]handler
  8. 返回 P

11 ECMAScript 语言:源文本

11.1 源文本

语法

SourceCharacter :: 任何 Unicode 码点

ECMAScript 源文本是一个 Unicode 码点序列。所有从 U+0000 到 U+10FFFF 的 Unicode 码点值,包括代理码点,都可以出现在 ECMAScript 语法允许的 ECMAScript 源文本中。用于存储和交换 ECMAScript 源文本的实际编码与本规范无关。无论外部源文本编码如何,符合要求的 ECMAScript 实现都会将源文本处理为等效的 SourceCharacter 值序列,每个 SourceCharacter 都是一个 Unicode 码点。符合要求的 ECMAScript 实现不需要对源文本执行任何规范化,也不需要表现得好像它们正在执行源文本规范化。

组合字符序列的组成部分被视为单独的 Unicode 码点,即使用户可能认为整个序列是一个字符。

在字符串字面量、正则表达式字面量、模板字面量和标识符中,任何 Unicode 码点也可以使用明确表示码点数值的 Unicode 转义序列来表示。在注释中,这样的转义序列作为注释的一部分被有效忽略。

ECMAScript 在 Unicode 转义序列的行为上与 Java 编程语言不同。在 Java 程序中,如果 Unicode 转义序列 \u000A 出现在单行注释中,它会被解释为行终止符(Unicode 码点 U+000A 是换行符 (LF)),因此下一个码点不是注释的一部分。同样,如果 Unicode 转义序列 \u000A 出现在 Java 程序的字符串字面量中,它同样被解释为行终止符,这在字符串字面量中是不允许的——必须写 \n 而不是 \u000A 来使换行符 (LF) 成为字符串字面量值的一部分。在 ECMAScript 程序中,出现在注释中的 Unicode 转义序列永远不会被解释,因此不能促成注释的终止。同样,出现在 ECMAScript 程序字符串字面量中的 Unicode 转义序列总是对字面量有贡献,永远不会被解释为行终止符或可能终止字符串字面量的码点。

11.1.1 静态语义:UTF16EncodeCodePoint ( cp )

抽象操作 UTF16EncodeCodePoint 接受参数 cp(一个 Unicode 码点)并返回一个字符串。它在被调用时执行以下步骤:

  1. 断言:0 ≤ cp ≤ 0x10FFFF。
  2. 如果 cp ≤ 0xFFFF,返回由数值为 cp 的码元组成的字符串值。
  3. cu1 为数值为 floor((cp - 0x10000) / 0x400) + 0xD800 的码元。
  4. cu2 为数值为 ((cp - 0x10000) modulo 0x400) + 0xDC00 的码元。
  5. 返回 cu1cu2字符串连接

11.1.2 静态语义:CodePointsToString ( text )

抽象操作 CodePointsToString 接受参数 text(一个 Unicode 码点序列)并返回一个字符串。它将 text 转换为字符串值,如 6.1.4 中所述。它在被调用时执行以下步骤:

  1. result 为空字符串。
  2. 对于 text 的每个码点 cp,执行
    1. 设置 resultresultUTF16EncodeCodePoint(cp) 的 字符串连接
  3. 返回 result

11.1.3 静态语义:UTF16SurrogatePairToCodePoint ( lead, trail )

抽象操作 UTF16SurrogatePairToCodePoint 接受参数 lead(一个码元)和 trail(一个码元)并返回一个码点。形成 UTF-16 代理对 的两个码元被转换为码点。它在被调用时执行以下步骤:

  1. 断言lead 是一个 前导代理trail 是一个 后尾代理
  2. cp 为 (lead - 0xD800) × 0x400 + (trail - 0xDC00) + 0x10000。
  3. 返回码点 cp

11.1.4 静态语义:CodePointAt ( string, position )

抽象操作 CodePointAt 接受参数 string(一个字符串)和 position(一个非负 整数)并返回一个具有字段 [[CodePoint]](一个码点)、[[CodeUnitCount]] (一个正 整数)和 [[IsUnpairedSurrogate]](一个布尔值)的 记录。它将 string 解释为 UTF-16 编码的码点序列,如 6.1.4 中所述,并从中读取一个从索引 position 处的码元开始的单个码点。它在被调用时执行以下步骤:

  1. sizestring 的长度。
  2. 断言position ≥ 0 且 position < size
  3. firststring 中索引 position 处的码元。
  4. cp 为数值等于 first 数值的码点。
  5. 如果 first 既不是 前导代理 也不是 后尾代理,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: false }。
  6. 如果 first后尾代理position + 1 = size,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  7. secondstring 中索引 position + 1 处的码元。
  8. 如果 second 不是 后尾代理,那么
    1. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 1, [[IsUnpairedSurrogate]]: true }。
  9. 设置 cpUTF16SurrogatePairToCodePoint(first, second)。
  10. 返回 记录 { [[CodePoint]]: cp, [[CodeUnitCount]]: 2, [[IsUnpairedSurrogate]]: false }。

11.1.5 静态语义:StringToCodePoints ( string )

抽象操作 StringToCodePoints 接受参数 string(一个字符串)并返回一个码点的 列表。它返回将 string 解释为 UTF-16 编码的 Unicode 文本所产生的 Unicode 码点序列,如 6.1.4 中所述。它在被调用时执行以下步骤:

  1. codePoints 为一个新的空 列表
  2. sizestring 的长度。
  3. position 为 0。
  4. 重复,当 position < size 时,
    1. cpCodePointAt(string, position)。
    2. cp.[[CodePoint]] 追加到 codePoints
    3. 设置 positionposition + cp.[[CodeUnitCount]]
  5. 返回 codePoints

11.1.6 静态语义:ParseText ( sourceText, goalSymbol )

抽象操作 ParseText 接受参数 sourceText(一个字符串或 Unicode 码点序列)和 goalSymbol(ECMAScript 语法中的一个非终结符)并返回一个 解析节点 或一个非空的 SyntaxError 对象 列表。它在被调用时执行以下步骤:

  1. 如果 sourceText 是一个字符串,设置 sourceTextStringToCodePoints(sourceText)。
  2. 尝试使用 goalSymbol 作为 目标符号 来解析 sourceText,并分析解析结果以查找任何 早期错误 条件。解析和 早期错误 检测可以以 实现定义 的方式交错进行。
  3. 如果解析成功且未发现 早期错误,返回解析产生的解析树根部的 解析节点goalSymbol 的一个实例)。
  4. 否则,返回一个包含一个或多个表示解析错误和/或 早期错误SyntaxError 对象的 列表。如果存在多个解析错误或 早期错误,列表中错误对象的数量和顺序是 实现定义 的,但至少必须存在一个。
注 1

考虑一个在特定点有 早期错误,在后面的点也有语法错误的文本。一个先执行解析阶段再执行 早期错误 阶段的实现可能会报告语法错误而不继续进行 早期错误 阶段。一个交错进行这两个活动的实现可能会报告 早期错误 而不继续查找语法错误。第三种实现可能会报告两个错误。所有这些行为都是符合要求的。

注 2

另见第 17 章。

11.2 源代码类型

ECMAScript 代码有四种类型:

注 1

函数代码通常作为函数定义(15.2)、箭头函数定义 (15.3)、方法定义 (15.4)、生成器函数定义 (15.5)、异步函数定义 (15.8)、异步生成器函数定义 (15.6) 和异步箭头函数(15.9)的主体提供。 函数代码也派生自 Function 构造函数20.2.1.1)、GeneratorFunction 构造函数27.3.1.1)和 AsyncFunction 构造函数27.7.1.1)的参数。

注 2

BindingIdentifier 包含在函数代码中的实际效果是,严格模式代码 的早期错误会应用于作为函数名称的 BindingIdentifier,该函数的主体包含 "use strict" 指令,即使周围的代码不是 严格模式代码

11.2.1 指令序言和 Use Strict 指令

指令序言是作为 FunctionBodyScriptBodyModuleBody 的初始 StatementListItemModuleItem 出现的最长 ExpressionStatement 序列,并且序列中的每个 ExpressionStatement 完全由一个 StringLiteral 标记后跟一个分号组成。分号可以显式出现,也可以通过自动分号插入(12.10)插入。一个 指令序言 可以是一个空序列。

Use Strict 指令指令序言 中的一个 ExpressionStatement,其 StringLiteral 是精确的码点序列 "use strict"'use strict'。一个 Use Strict 指令 不能包含 EscapeSequenceLineContinuation

一个 指令序言 可能包含多个 Use Strict 指令。但是,如果发生这种情况,实现可能会发出警告。

指令序言ExpressionStatement 在包含的产生式求值期间正常求值。实现可以为那些不是 Use Strict 指令 且出现在 指令序言 中的 ExpressionStatement 定义实现特定的含义。如果存在适当的通知机制,当实现在 指令序言 中遇到一个不是 Use Strict 指令 且没有由实现定义的含义的 ExpressionStatement 时,应发出警告。

11.2.2 严格模式代码

ECMAScript 句法单元可以使用非限制性或严格模式语法和语义(4.3.2)进行处理。在以下情况下,代码被解释为 严格模式代码

不是严格模式代码的 ECMAScript 代码称为 非严格代码

11.2.2.1 静态语义:IsStrict ( node )

抽象操作 IsStrict 接受参数 node(一个 解析节点)并返回一个布尔值。它在被调用时执行以下步骤:

  1. 如果 node 匹配的源文本严格模式代码,返回 true;否则返回 false

11.2.3 非 ECMAScript 函数

ECMAScript 实现可以支持对函数 奇异对象 的求值,其求值行为以某种 宿主定义 的可执行代码形式表示,而不是 ECMAScript 源文本。从调用或被此类 函数对象 调用的 ECMAScript 代码的角度来看,函数对象 是在 ECMAScript 代码中定义的还是内置函数是不可观察的。

12 ECMAScript 语言:词法语法

ECMAScript 脚本模块 的源文本首先被转换为输入元素序列,这些输入元素是标记、行终止符、注释或空白符。源文本从左到右扫描,重复地取尽可能长的码点序列作为下一个输入元素。

在某些情况下,词法输入元素的识别对消费输入元素的句法语法上下文很敏感。这需要词法语法具有多个 目标符号InputElementHashbangOrRegExp 目标用于 脚本模块 的开始。InputElementRegExpOrTemplateTail 目标用于允许 RegularExpressionLiteralTemplateMiddleTemplateTail 的句法语法上下文中。InputElementRegExp 目标符号 用于所有允许 RegularExpressionLiteral 但不允许 TemplateMiddleTemplateTail 的句法语法上下文中。InputElementTemplateTail 目标用于所有允许 TemplateMiddleTemplateTail 但不允许 RegularExpressionLiteral 的句法语法上下文中。在所有其他上下文中,InputElementDiv 用作词法 目标符号

使用多个词法目标确保不存在会影响自动分号插入的词法歧义。例如,不存在既允许前导除法或除法赋值又允许前导 RegularExpressionLiteral 的句法语法上下文。这不受分号插入的影响(参见 12.10);在如下例子中:

a = b
/hi/g.exec(c).map(d);

其中 LineTerminator 后第一个非空白、非注释码点是 U+002F(斜线),且句法上下文允许除法或除法赋值,则不会在 LineTerminator 处插入分号。也就是说,上述例子的解释方式与以下相同:

a = b / hi / g.exec(c).map(d);

语法

InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral

12.1 Unicode 格式控制字符

Unicode 格式控制字符(即 Unicode 字符数据库中类别为 "Cf" 的字符,如从左到右标记或从右到左标记)是在缺乏用于此目的的高级协议(如标记语言)的情况下用于控制文本范围格式的控制代码。

允许格式控制字符出现在源文本中是有用的,以便于编辑和显示。所有格式控制字符都可以在注释中以及字符串字面量、模板字面量和正则表达式字面量中使用。

U+FEFF(零宽度无间断空格)是一个格式控制字符,主要用于文本的开头,以将其标记为 Unicode 并允许检测文本的编码和字节顺序。用于此目的的 <ZWNBSP> 字符有时也可能出现在文本开头之后,例如作为连接文件的结果。在 ECMAScript 源文本 中,<ZWNBSP> 码点在注释、字符串字面量、模板字面量和正则表达式字面量之外被视为空白字符(参见 12.2)。

12.2 空白符

空白码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离,但在其他方面是无关紧要的。空白码点可以出现在任意两个标记之间以及输入的开始或结束处。空白码点可以出现在 StringLiteralRegularExpressionLiteralTemplateTemplateSubstitutionTail 中,在这些地方它们被视为构成字面量值一部分的重要码点。它们也可以出现在 Comment 中,但不能出现在任何其他类型的标记内。

ECMAScript 空白码点列在 表 35 中。

表 35:空白码点
码点 名称 缩写
U+0009 字符制表符 <TAB>
U+000B 行制表符 <VT>
U+000C 换页符 (FF) <FF>
U+FEFF 零宽度无间断空格 <ZWNBSP>
通用类别 "Space_Separator" 中的任何码点 <USP>
注 1

U+0020(空格)和 U+00A0(无间断空格)码点是 <USP> 的一部分。

注 2

除了 表 35 中列出的码点外,ECMAScript WhiteSpace 有意排除了所有具有 Unicode "White_Space" 属性但未归类为通用类别 "Space_Separator"("Zs")的码点。

语法

WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP>

12.3 行终止符

与空白码点一样,行终止符码点用于改善源文本的可读性并将标记(不可分割的词法单元)彼此分离。但是,与空白码点不同,行终止符对句法语法的行为有一定影响。通常,行终止符可以出现在任意两个标记之间,但在句法语法禁止的少数地方则不行。行终止符还会影响自动分号插入的过程(12.10)。行终止符不能出现在任何标记内,除了 StringLiteralTemplateTemplateSubstitutionTail。<LF> 和 <CR> 行终止符不能出现在 StringLiteral 标记内,除非作为 LineContinuation 的一部分。

行终止符可以出现在 MultiLineComment 内,但不能出现在 SingleLineComment 内。

行终止符被包含在正则表达式中 \s 类匹配的空白码点集合中。

ECMAScript 行终止符码点列在 表 36 中。

表 36:行终止符码点
码点 Unicode 名称 缩写
U+000A 换行符 (LF) <LF>
U+000D 回车符 (CR) <CR>
U+2028 行分隔符 <LS>
U+2029 段分隔符 <PS>

只有 表 36 中的 Unicode 码点被视为行终止符。其他换行或断行的 Unicode 码点不被视为行终止符,但如果它们满足 表 35 中列出的要求,则被视为空白符。序列 <CR><LF> 通常用作行终止符。为了报告行号的目的,它应该被视为单个 SourceCharacter

语法

LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF>

12.4 注释

注释可以是单行或多行的。多行注释不能嵌套。

由于单行注释可以包含除 LineTerminator 码点之外的任何 Unicode 码点,并且由于标记总是尽可能长的一般规则,单行注释总是由从 // 标记到行尾的所有码点组成。但是,行尾的 LineTerminator 不被认为是单行注释的一部分;它由词法语法单独识别,并成为句法语法输入元素流的一部分。这一点非常重要,因为这意味着单行注释的存在或不存在不会影响自动分号插入的过程(参见 12.10)。

注释的行为类似空白符并被丢弃,除非 MultiLineComment 包含行终止符码点,则整个注释在句法语法解析时被视为 LineTerminator

语法

Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator

本节中的许多产生式在 B.1.1 节中给出了替代定义

12.5 Hashbang 注释

Hashbang 注释对位置敏感,与其他类型的注释一样,从句法语法的输入元素流中被丢弃。

语法

HashbangComment :: #! SingleLineCommentCharsopt

12.6 标记

语法

CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template

DivPunctuatorRegularExpressionLiteralRightBracePunctuatorTemplateSubstitutionTail 产生式派生出额外的标记,这些标记不包含在 CommonToken 产生式中。

12.7 名称和关键字

IdentifierNameReservedWord 是根据 Unicode 标准附件 #31《标识符和模式语法》中给定的默认标识符语法进行解释的标记,但有一些小的修改。ReservedWordIdentifierName 的一个枚举子集。句法语法将 Identifier 定义为不是 ReservedWordIdentifierName。Unicode 标识符语法基于 Unicode 标准规定的字符属性。所有符合的 ECMAScript 实现必须将最新版本 Unicode 标准中指定类别的 Unicode 码点视为属于那些类别。ECMAScript 实现可以识别在 Unicode 标准后续版本中定义的标识符码点。

注 1

本标准规定了特定的码点添加:U+0024(美元符号)和 U+005F(下划线)允许出现在 IdentifierName 的任何位置。

语法

PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: 任何具有 Unicode 属性 "ID_Start" 的 Unicode 码点 UnicodeIDContinue :: 任何具有 Unicode 属性 "ID_Continue" 的 Unicode 码点

非终结符 UnicodeEscapeSequence 的定义在 12.9.4 中给出。

注 2

非终结符 IdentifierPart 通过 UnicodeIDContinue 派生 _

注 3

具有 Unicode 属性 "ID_Start" 和 "ID_Continue" 的码点集合分别包括具有 Unicode 属性 "Other_ID_Start" 和 "Other_ID_Continue" 的码点。

12.7.1 标识符名称

Unicode 转义序列在 IdentifierName 中是允许的,它们贡献一个等于 UnicodeEscapeSequenceIdentifierCodePoint 的单个 Unicode 码点。UnicodeEscapeSequence 前面的 \ 不贡献任何码点。UnicodeEscapeSequence 不能用于为 IdentifierName 贡献一个本来无效的码点。换句话说,如果 \ UnicodeEscapeSequence 序列被它所贡献的 SourceCharacter 替换,结果仍然必须是一个有效的 IdentifierName,且具有与原始 IdentifierName 完全相同的 SourceCharacter 元素序列。本规范中对 IdentifierName 的所有解释都基于它们的实际码点,无论是否使用转义序列来贡献任何特定码点。

根据 Unicode 标准规范等价的两个 IdentifierName相等的,除非在替换每个 UnicodeEscapeSequence 后,它们由完全相同的码点序列表示。

12.7.1.1 静态语义:早期错误

IdentifierStart :: \ UnicodeEscapeSequence IdentifierPart :: \ UnicodeEscapeSequence

12.7.1.2 静态语义:IdentifierCodePoints

语法导向操作 IdentifierCodePoints 不接受参数并返回码点的 列表。它在以下产生式上分段定义:

IdentifierName :: IdentifierStart
  1. cpIdentifierStartIdentifierCodePoint
  2. 返回 « cp »。
IdentifierName :: IdentifierName IdentifierPart
  1. cps 为派生的 IdentifierNameIdentifierCodePoints
  2. cpIdentifierPartIdentifierCodePoint
  3. 返回 cps 和 « cp » 的 列表连接

12.7.1.3 静态语义:IdentifierCodePoint

语法导向操作 IdentifierCodePoint 不接受参数并返回一个码点。它在以下产生式上分段定义:

IdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 匹配的码点。
IdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 匹配的码点。
UnicodeEscapeSequence :: u Hex4Digits
  1. 返回数值等于 Hex4Digits 的 MV 的码点。
UnicodeEscapeSequence :: u{ CodePoint }
  1. 返回数值等于 CodePoint 的 MV 的码点。

12.7.2 关键字和保留字

关键字是匹配 IdentifierName 但也有句法用途的标记;也就是说,它在某些句法产生式中以固定宽度字体直接出现。ECMAScript 的关键字包括 ifwhileasyncawait 等等。

保留字是不能用作标识符的 IdentifierName。许多关键字是保留字,但有些不是,有些只在特定上下文中保留。ifwhile 是保留字。await 只在异步函数和模块内保留。async 不是保留的;它可以无限制地用作变量名或语句标签。

本规范使用语法产生式和 早期错误 规则的组合来指定哪些名称是有效标识符,哪些是保留字。下面 ReservedWord 列表中的所有标记,除了 awaityield,都是无条件保留的。awaityield 的例外在 13.1 中使用参数化句法产生式指定。最后,几个 早期错误 规则限制有效标识符的集合。参见 13.1.114.3.1.114.7.5.115.7.1。总结来说,标识符名称有五个类别:

  • 总是允许作为标识符且不是关键字的,如 MathwindowtoString_

  • 从不允许作为标识符的,即下面列出的 ReservedWord(除了 awaityield);

  • 上下文允许作为标识符的,即 awaityield

  • 严格模式代码 中上下文不允许作为标识符的:letstaticimplementsinterfacepackageprivateprotectedpublic

  • 总是允许作为标识符,但也在某些句法产生式中作为关键字出现,在不允许 Identifier 的地方:asasyncfromgetmetaofsettarget

条件关键字上下文关键字这个术语有时用来指属于后三个类别的关键字,因此可以在某些上下文中用作标识符,在其他上下文中用作关键字。

语法

ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield 注 1

根据 5.1.5,语法中的关键字匹配特定 SourceCharacter 元素的文字序列。关键字中的码点不能用 \ UnicodeEscapeSequence 表示。

IdentifierName 可以包含 \ UnicodeEscapeSequence,但不可能通过拼写 els\u{65} 来声明名为 "else" 的变量。13.1.1 中的 早期错误 规则排除了与保留字具有相同 StringValue 的标识符。

注 2

enum 目前在本规范中未用作关键字。它是一个未来保留字,留作未来语言扩展中用作关键字。

类似地,implementsinterfacepackageprivateprotectedpublic严格模式代码 中是未来保留字。

注 3

名称 argumentseval 不是关键字,但它们在 严格模式代码 中受到一些限制。参见 13.1.18.6.415.2.115.5.115.6.115.8.1

12.8 标点符号

语法

Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: }

12.9 字面量

12.9.1 Null 字面量

语法

NullLiteral :: null

12.9.2 布尔字面量

语法

BooleanLiteral :: true false

12.9.3 数值字面量

语法

NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: 0 NonZeroDigit NonZeroDigit NumericLiteralSeparatoropt DecimalDigits[+Sep] NonOctalDecimalIntegerLiteral DecimalDigits[Sep] :: DecimalDigit DecimalDigits[?Sep] DecimalDigit [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9 ExponentPart[Sep] :: ExponentIndicator SignedInteger[?Sep] ExponentIndicator :: one of e E SignedInteger[Sep] :: DecimalDigits[?Sep] + DecimalDigits[?Sep] - DecimalDigits[?Sep] BinaryIntegerLiteral[Sep] :: 0b BinaryDigits[?Sep] 0B BinaryDigits[?Sep] BinaryDigits[Sep] :: BinaryDigit BinaryDigits[?Sep] BinaryDigit [+Sep] BinaryDigits[+Sep] NumericLiteralSeparator BinaryDigit BinaryDigit :: one of 0 1 OctalIntegerLiteral[Sep] :: 0o OctalDigits[?Sep] 0O OctalDigits[?Sep] OctalDigits[Sep] :: OctalDigit OctalDigits[?Sep] OctalDigit [+Sep] OctalDigits[+Sep] NumericLiteralSeparator OctalDigit LegacyOctalIntegerLiteral :: 0 OctalDigit LegacyOctalIntegerLiteral OctalDigit NonOctalDecimalIntegerLiteral :: 0 NonOctalDigit LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalIntegerLiteral :: 0 OctalDigit LegacyOctalLikeDecimalIntegerLiteral OctalDigit OctalDigit :: one of 0 1 2 3 4 5 6 7 NonOctalDigit :: one of 8 9 HexIntegerLiteral[Sep] :: 0x HexDigits[?Sep] 0X HexDigits[?Sep] HexDigits[Sep] :: HexDigit HexDigits[?Sep] HexDigit [+Sep] HexDigits[+Sep] NumericLiteralSeparator HexDigit HexDigit :: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F

紧跟在 NumericLiteral 后面的 SourceCharacter 不能是 IdentifierStartDecimalDigit

例如:3in 是一个错误,而不是两个输入元素 3in

12.9.3.1 静态语义:早期错误

NumericLiteral :: LegacyOctalIntegerLiteral DecimalIntegerLiteral :: NonOctalDecimalIntegerLiteral
  • 如果 IsStrict(this production) 是 true,则这是语法错误。
非严格代码 中,此语法是 遗留 的。

12.9.3.2 静态语义:MV

数值字面量表示 Number 类型BigInt 类型 的值。

12.9.3.3 静态语义:NumericValue

语法导向操作 NumericValue 不接受参数并返回一个 Number 或 BigInt。它在以下产生式上分段定义:

NumericLiteral :: DecimalLiteral
  1. 返回 RoundMVResult(DecimalLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral
  1. 返回 𝔽(NonDecimalIntegerLiteral 的 MV)。
NumericLiteral :: LegacyOctalIntegerLiteral
  1. 返回 𝔽(LegacyOctalIntegerLiteral 的 MV)。
NumericLiteral :: NonDecimalIntegerLiteral BigIntLiteralSuffix
  1. 返回 NonDecimalIntegerLiteral 的 MV 的 BigInt 值
DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix
  1. 返回 0
DecimalBigIntegerLiteral :: NonZeroDigit BigIntLiteralSuffix
  1. 返回 NonZeroDigit 的 MV 的 BigInt 值
DecimalBigIntegerLiteral :: NonZeroDigit DecimalDigits BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits BigIntLiteralSuffix
  1. nDecimalDigits 中的码点数,不包括所有 NumericLiteralSeparator 的出现。
  2. mv 为(NonZeroDigit 的 MV × 10n)加上 DecimalDigits 的 MV。
  3. 返回 (mv)。

12.9.4 字符串字面量

注 1

字符串字面量是用单引号或双引号括起来的 0 个或多个 Unicode 码点。Unicode 码点也可以用转义序列表示。除了结束引号码点、U+005C(反斜杠)、U+000D(回车符)和 U+000A(换行符)之外,所有码点都可以直接出现在字符串字面量中。任何码点都可以以转义序列的形式出现。字符串字面量求值为 ECMAScript String 值。生成这些 String 值时,Unicode 码点按照 11.1.1 中定义的方式进行 UTF-16 编码。属于基本多语言平面的码点被编码为字符串的单个码元素。所有其他码点被编码为字符串的两个码元素。

语法

StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit

非终结符 HexDigit 的定义在 12.9.3 中给出。SourceCharacter11.1 中定义。

注 2

<LF> 和 <CR> 不能出现在字符串字面量中,除非作为 LineContinuation 的一部分来产生空码点序列。在字符串字面量的 String 值中包含它们的正确方法是使用转义序列,如 \n\u000A

12.9.4.1 静态语义:早期错误

EscapeSequence :: LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence
  • 如果 IsStrict(this production) 是 true,则这是语法错误。
注 1
非严格代码 中,此语法是 遗留 的。
注 2

字符串字面量可能出现在将封闭代码置于 严格模式Use Strict 指令 之前,实现必须注意对这类字面量强制执行上述规则。例如,以下源文本包含语法错误:

function invalid() { "\7"; "use strict"; }

12.9.4.2 静态语义:SV

语法导向操作 SV 不接受参数并返回一个 String。

字符串字面量表示 String 类型 的值。SV 通过对字符串字面量的各个部分进行递归应用来为字符串字面量产生 String 值。作为此过程的一部分,字符串字面量内的一些 Unicode 码点被解释为具有 数学值,如下所述或在 12.9.3 中所述。

表 37:字符串单字符转义序列
转义序列 码元值 Unicode 字符名称 符号
\b 0x0008 BACKSPACE <BS>
\t 0x0009 CHARACTER TABULATION <HT>
\n 0x000A LINE FEED (LF) <LF>
\v 0x000B LINE TABULATION <VT>
\f 0x000C FORM FEED (FF) <FF>
\r 0x000D CARRIAGE RETURN (CR) <CR>
\" 0x0022 QUOTATION MARK "
\' 0x0027 APOSTROPHE '
\\ 0x005C REVERSE SOLIDUS \

12.9.4.3 静态语义:MV

12.9.5 正则表达式字面量

注 1

正则表达式字面量是一个输入元素,每次求值该字面量时都会被转换为 RegExp 对象(参见 22.2)。程序中的两个正则表达式字面量求值为正则表达式对象,即使两个字面量的内容相同,它们也永远不会比较为 ===。RegExp 对象也可以在运行时通过 new RegExp 或调用 RegExp 构造函数 作为函数来创建(参见 22.2.4)。

下面的产生式描述了正则表达式字面量的语法,并被输入元素扫描器用来找到正则表达式字面量的结尾。包含 RegularExpressionBodyRegularExpressionFlags 的源文本随后使用更严格的 ECMAScript 正则表达式语法(22.2.1)再次解析。

实现可以扩展在 22.2.1 中定义的 ECMAScript 正则表达式语法,但不得扩展下面定义的 RegularExpressionBodyRegularExpressionFlags 产生式或这些产生式使用的产生式。

语法

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar 注 2

正则表达式字面量不能为空;码元序列 // 不是表示空正则表达式字面量,而是开始单行注释。要指定空正则表达式,请使用:/(?:)/

12.9.5.1 静态语义:BodyText

语法导向操作 BodyText 不接受参数并返回源文本。它在以下产生式上分段定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionBody 的源文本。

12.9.5.2 静态语义:FlagText

语法导向操作 FlagText 不接受参数并返回源文本。它在以下产生式上分段定义:

RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags
  1. 返回被识别为 RegularExpressionFlags 的源文本。

12.9.6 模板字面量词法组件

语法

Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF

TemplateSubstitutionTailInputElementTemplateTail 替代词法目标使用。

12.9.6.1 静态语义:TV

语法导向操作 TV 不接受参数并返回 String 或 undefined。模板字面量组件被 TV 解释为 String 类型 的值。TV 用于构造模板对象的索引组件(通俗地说,模板值)。在 TV 中,转义序列被转义序列表示的 Unicode 码点的 UTF-16 码元替换。

12.9.6.2 静态语义:TRV

语法导向操作 TRV 不接受参数并返回 String。模板字面量组件被 TRV 解释为 String 类型 的值。TRV 用于构造模板对象的原始组件(通俗地说,模板原始值)。TRV 类似于 TV,区别在于在 TRV 中,转义序列按照它们在字面量中出现的方式被解释。

TV 排除 LineContinuation 的码元,而 TRV 包含它们。<CR><LF> 和 <CR> LineTerminatorSequence 对于 TV 和 TRV 都被规范化为 <LF>。需要显式的 TemplateEscapeSequence 来包含 <CR> 或 <CR><LF> 序列。

12.10 自动分号插入

大多数 ECMAScript 语句和声明必须以分号结尾。这些分号可以始终显式地出现在源文本中。但是,为了方便起见,在某些情况下可以从源文本中省略这些分号。这些情况通过说分号在这些情况下被自动插入到源代码标记流中来描述。

12.10.1 自动分号插入规则

在以下规则中,"标记"是指使用当前词法目标符号确定的实际识别的词法标记,如第 12 章所述。

分号插入有三个基本规则:

  1. 当从左到右解析源文本时,遇到语法的任何产生式都不允许的标记(称为违规标记),如果满足以下一个或多个条件,则在违规标记之前自动插入分号:

    • 违规标记与前一个标记之间至少有一个 LineTerminator 分隔。
    • 违规标记是 }
    • 前一个标记是 ),插入的分号将被解析为 do-while 语句的终止分号(14.7.2)。
  2. 当从左到右解析源文本时,遇到标记输入流的结尾,并且解析器无法将输入标记流解析为目标非终结符的单个实例,则在输入流的结尾自动插入分号。
  3. 当从左到右解析源文本时,遇到语法的某些产生式允许的标记,但该产生式是受限产生式,并且该标记将是紧接着受限产生式中注释"[no LineTerminator here]"之后的终结符或非终结符的第一个标记(因此这样的标记称为受限标记),并且受限标记与前一个标记之间至少有一个 LineTerminator 分隔,则在受限标记之前自动插入分号。

但是,前述规则有一个额外的覆盖条件:如果分号随后会被解析为空语句,或者该分号会成为 for 语句头部中的两个分号之一(参见 14.7.4),则永远不会自动插入分号。

以下是语法中唯一的受限产生式:

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

这些受限产生式的实际效果如下:

  • 当遇到 ++-- 标记时,解析器会将其视为后缀运算符,如果在前一个标记和 ++-- 标记之间至少有一个 LineTerminator,则在 ++-- 标记之前自动插入分号。
  • 当遇到 continuebreakreturnthrowyield 标记,并且在下一个标记之前遇到 LineTerminator 时,在 continuebreakreturnthrowyield 标记之后自动插入分号。
  • 当箭头函数参数后面在 => 标记之前有 LineTerminator 时,自动插入分号,标点符号会导致语法错误。
  • async 标记后面在 functionIdentifierName( 标记之前有 LineTerminator 时,自动插入分号,async 标记不被视为与后续标记相同表达式或类元素的一部分。
  • async 标记后面在 * 标记之前有 LineTerminator 时,自动插入分号,标点符号会导致语法错误。

给 ECMAScript 程序员的实际建议是:

  • 后缀 ++-- 运算符应该与其操作数在同一行。
  • returnthrow 语句中的 Expressionyield 表达式中的 AssignmentExpression 应该与 returnthrowyield 标记在同一行开始。
  • breakcontinue 语句中的 LabelIdentifier 应该与 breakcontinue 标记在同一行。
  • 箭头函数参数的结尾和其 => 应该在同一行。
  • 异步函数或方法前面的 async 标记应该与紧接着的标记在同一行。

12.10.2 自动分号插入示例

本节是非规范性的。

源代码

{ 1 2 } 3

不是 ECMAScript 语法中的有效句子,即使有自动分号插入规则。相反,源代码

{ 1
2 } 3

也不是有效的 ECMAScript 句子,但通过自动分号插入转换为以下内容:

{ 1
;2 ;} 3;

这是一个有效的 ECMAScript 句子。

源代码

for (a; b
)

不是有效的 ECMAScript 句子,并且不会被自动分号插入更改,因为 for 语句的头部需要分号。自动分号插入永远不会插入 for 语句头部中的两个分号之一。

源代码

return
a + b

通过自动分号插入转换为以下内容:

return;
a + b;
注 1

表达式 a + b 不被视为 return 语句要返回的值,因为 LineTerminator 将其与标记 return 分开。

源代码

a = b
++c

通过自动分号插入转换为以下内容:

a = b;
++c;
注 2

标记 ++ 不被视为应用于变量 b 的后缀运算符,因为 LineTerminator 出现在 b++ 之间。

源代码

if (a > b)
else c = d

不是有效的 ECMAScript 句子,并且不会被自动分号插入在 else 标记之前更改,即使在该点语法的任何产生式都不适用,因为自动插入的分号随后会被解析为空语句。

源代码

a = b + c
(d + e).print()

不会被自动分号插入转换,因为第二行开始的括号表达式可以被解释为函数调用的参数列表:

a = b + c(d + e).print()

在赋值语句必须以左括号开始的情况下,程序员最好在前一个语句的末尾提供显式分号,而不是依赖自动分号插入。

12.10.3 自动分号插入的有趣情况

本节是非规范性的。

ECMAScript 程序可以通过依赖自动分号插入以很少分号的风格编写。如上所述,分号不会在每个换行符处插入,自动分号插入可能依赖于跨行终止符的多个标记。

随着新的语法特性被添加到 ECMAScript 中,可能会添加额外的语法产生式,这些产生式会导致依赖自动分号插入的行在解析时改变语法产生式。

就本节而言,如果自动分号插入的情况是可能插入或不插入分号的地方,取决于其前面的源文本,则被认为是有趣的。本节的其余部分描述了这个版本的 ECMAScript 中自动分号插入的许多有趣情况。

12.10.3.1 语句列表中自动分号插入的有趣情况

StatementList 中,许多 StatementListItem 以分号结尾,这些分号可以使用自动分号插入省略。根据上述规则,在结束表达式的行末尾,如果下一行以以下任何内容开始,则需要分号:

  • 左括号 (()。没有分号时,两行一起被视为 CallExpression
  • 左方括号 ([)。没有分号时,两行一起被视为属性访问,而不是 ArrayLiteralArrayAssignmentPattern
  • 模板字面量 (`)。没有分号时,两行一起被解释为带标签的模板(13.3.11),前面的表达式作为 MemberExpression
  • 一元 +-。没有分号时,两行一起被解释为使用相应二元运算符。
  • 正则表达式字面量。没有分号时,两行一起可能被解析为 / MultiplicativeOperator,例如如果正则表达式有标志。

12.10.3.2 自动分号插入和"[no LineTerminator here]"的情况

本节是非规范性的。

ECMAScript 包含包括"[no LineTerminator here]"的语法产生式。这些产生式有时是在语法中拥有可选操作数的手段。在这些位置引入 LineTerminator 会通过使用没有可选操作数的语法产生式来改变源文本的语法产生式。

本节的其余部分描述了这个版本的 ECMAScript 中使用"[no LineTerminator here]"的许多产生式。

12.10.3.2.1 带有可选操作数和"[no LineTerminator here]"的语法产生式列表

13 ECMAScript 语言:表达式

13.1 标识符

语法

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord

yieldawait 在语法中被允许作为 BindingIdentifier,并在下面的静态语义中被禁止,以防止在以下情况中自动分号插入

let
await 0;

13.1.1 静态语义:早期错误

BindingIdentifier : Identifier IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  • 如果 IsStrict(this production) 是 true,则是语法错误。
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await BindingIdentifier[Yield, Await] : yield
  • 如果此产生式有 [Yield] 参数,则是语法错误。
BindingIdentifier[Yield, Await] : await
  • 如果此产生式有 [Await] 参数,则是语法错误。
IdentifierReference[Yield, Await] : Identifier BindingIdentifier[Yield, Await] : Identifier LabelIdentifier[Yield, Await] : Identifier
  • 如果此产生式有 [Yield] 参数并且 IdentifierStringValue"yield",则是语法错误。
  • 如果此产生式有 [Await] 参数并且 IdentifierStringValue"await",则是语法错误。
Identifier : IdentifierName but not ReservedWord

IdentifierNameStringValue 规范化 IdentifierName 中的任何 Unicode 转义序列,因此这些转义不能用于编写代码点序列与 ReservedWord 相同的 Identifier

13.1.2 静态语义:StringValue

语法导向操作 StringValue 不接受参数并返回 String。它在以下产生式上分段定义:

IdentifierName :: IdentifierStart IdentifierName IdentifierPart
  1. idTextUnescapedIdentifierNameIdentifierCodePoints
  2. 返回 CodePointsToString(idTextUnescaped)。
IdentifierReference : yield BindingIdentifier : yield LabelIdentifier : yield
  1. 返回 "yield"
IdentifierReference : await BindingIdentifier : await LabelIdentifier : await
  1. 返回 "await"
Identifier : IdentifierName but not ReservedWord
  1. 返回 IdentifierNameStringValue
PrivateIdentifier :: # IdentifierName
  1. 返回 0x0023(数字符号)与 IdentifierNameStringValue字符串连接
ModuleExportName : StringLiteral
  1. 返回 StringLiteralSV

13.1.3 运行时语义:Evaluation

IdentifierReference : Identifier
  1. 返回 ? ResolveBinding(IdentifierStringValue)。
IdentifierReference : yield
  1. 返回 ? ResolveBinding("yield")。
IdentifierReference : await
  1. 返回 ? ResolveBinding("await")。
注 1

求值 IdentifierReference 的结果总是 Reference 类型的值。

注 2

非严格代码中,关键字 yield 可以用作标识符。求值 IdentifierReference 解析 yield 的绑定,就像它是 Identifier 一样。早期错误限制确保这种求值只能在非严格代码中发生。

13.2 主表达式

语法

PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

补充语法

当处理产生式的实例时
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
CoverParenthesizedExpressionAndArrowParameterList 的解释使用以下语法进行细化:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

13.2.1 this 关键字

13.2.1.1 运行时语义:Evaluation

PrimaryExpression : this
  1. 返回 ? ResolveThisBinding()。

13.2.2 标识符引用

关于 IdentifierReference,请参见 13.1

13.2.3 字面量

语法

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral

13.2.3.1 运行时语义:Evaluation

Literal : NullLiteral
  1. 返回 null
Literal : BooleanLiteral
  1. 如果 BooleanLiteral 是标记 false,返回 false
  2. 如果 BooleanLiteral 是标记 true,返回 true
Literal : NumericLiteral
  1. 返回 NumericLiteralNumericValue,如 12.9.3 中定义。
Literal : StringLiteral
  1. 返回 StringLiteralSV,如 12.9.4.2 中定义。

13.2.4 数组初始化器

ArrayLiteral 是一个表达式,描述使用零个或多个表达式的列表来初始化数组,每个表达式代表一个数组元素,包含在方括号中。元素不需要是字面量;每次求值数组初始化器时都会对它们进行求值。

数组元素可以在元素列表的开头、中间或末尾省略。当元素列表中的逗号前面没有 AssignmentExpression(即开头的逗号或另一个逗号后面的逗号)时,缺失的数组元素会增加数组的长度并增加后续元素的索引。省略的数组元素未定义。如果在数组末尾省略了元素,该元素不会增加数组的长度。

语法

ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await]

13.2.4.1 运行时语义:ArrayAccumulation

语法导向操作 ArrayAccumulation 接受参数 array(一个数组)和 nextIndex(一个整数)并返回包含一个整数正常完成或一个突然完成。它在以下产生式上分段定义:

Elision : ,
  1. lennextIndex + 1。
  2. 执行 ? Set(array, "length", 𝔽(len), true)。
  3. 注:如果 len 超过 232 - 1,上述步骤会抛出异常。
  4. 返回 len
Elision : Elision ,
  1. 返回 ? Elision 与参数 array 和 (nextIndex + 1) 的 ArrayAccumulation
ElementList : Elisionopt AssignmentExpression
  1. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  2. initResult 为 ? AssignmentExpressionEvaluation
  3. initValue 为 ? GetValue(initResult)。
  4. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  5. 返回 nextIndex + 1。
ElementList : Elisionopt SpreadElement
  1. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  2. 返回 ? SpreadElement 与参数 arraynextIndexArrayAccumulation
ElementList : ElementList , Elisionopt AssignmentExpression
  1. 设置 nextIndex 为 ? ElementList 与参数 arraynextIndexArrayAccumulation
  2. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  3. initResult 为 ? AssignmentExpressionEvaluation
  4. initValue 为 ? GetValue(initResult)。
  5. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), initValue)。
  6. 返回 nextIndex + 1。
ElementList : ElementList , Elisionopt SpreadElement
  1. 设置 nextIndex 为 ? ElementList 与参数 arraynextIndexArrayAccumulation
  2. 如果 Elision 存在,则
    1. 设置 nextIndex 为 ? Elision 与参数 arraynextIndexArrayAccumulation
  3. 返回 ? SpreadElement 与参数 arraynextIndexArrayAccumulation
SpreadElement : ... AssignmentExpression
  1. spreadRef 为 ? AssignmentExpressionEvaluation
  2. spreadObj 为 ? GetValue(spreadRef)。
  3. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 nextIndex
    3. 执行 ! CreateDataPropertyOrThrow(array, ! ToString(𝔽(nextIndex)), next)。
    4. 设置 nextIndexnextIndex + 1。

使用 CreateDataPropertyOrThrow 来确保为数组定义自己的属性,即使标准内置的Array 原型对象已经以会阻止使用 [[Set]] 创建新自己属性的方式被修改。

13.2.4.2 运行时语义:Evaluation

ArrayLiteral : [ Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. 如果 Elision 存在,则
    1. 执行 ? Elision 与参数 array 和 0 的 ArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList ]
  1. array 为 ! ArrayCreate(0)。
  2. 执行 ? ElementList 与参数 array 和 0 的 ArrayAccumulation
  3. 返回 array
ArrayLiteral : [ ElementList , Elisionopt ]
  1. array 为 ! ArrayCreate(0)。
  2. nextIndex 为 ? ElementList 与参数 array 和 0 的 ArrayAccumulation
  3. 如果 Elision 存在,则
    1. 执行 ? Elision 与参数 arraynextIndexArrayAccumulation
  4. 返回 array

13.2.5 对象初始化器

注 1

对象初始化器是一个表达式,描述对象的初始化,以类似字面量的形式编写。它是零个或多个属性键和关联值的对的列表,包含在花括号中。值不需要是字面量;每次求值对象初始化器时都会对它们进行求值。

语法

ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] 注 2

MethodDefinition15.4 中定义。

注 3

在某些上下文中,ObjectLiteral 用作更受限制的次级语法的覆盖语法。CoverInitializedName 产生式是完全覆盖这些次级语法所必需的。但是,在期望实际 ObjectLiteral 的正常上下文中,使用此产生式会导致早期语法错误。

13.2.5.1 静态语义:早期错误

PropertyDefinition : MethodDefinition

除了描述实际的对象初始化器之外,ObjectLiteral 产生式还用作 ObjectAssignmentPattern 的覆盖语法,并且可能被识别为 CoverParenthesizedExpressionAndArrowParameterList 的一部分。当 ObjectLiteral 出现在需要 ObjectAssignmentPattern 的上下文中时,以下早期错误规则适用。此外,在最初解析 CoverParenthesizedExpressionAndArrowParameterListCoverCallExpressionAndAsyncArrowHead 时,它们也不适用。

PropertyDefinition : CoverInitializedName
  • 如果任何源文本与此产生式匹配,则是语法错误。
注 1

此产生式的存在是为了让 ObjectLiteral 可以作为 ObjectAssignmentPattern 的覆盖语法。它不能出现在实际的对象初始化器中。

ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , } 注 2

PropertyNameList 返回的列表不包括使用 ComputedPropertyName 定义的属性名。

13.2.5.2 静态语义:IsComputedPropertyKey

语法导向操作 IsComputedPropertyKey 不接受参数并返回布尔值。它在以下产生式上分段定义:

PropertyName : LiteralPropertyName
  1. 返回 false
PropertyName : ComputedPropertyName
  1. 返回 true

13.2.5.3 静态语义:PropertyNameList

语法导向操作 PropertyNameList 不接受参数并返回字符串的列表。它在以下产生式上分段定义:

PropertyDefinitionList : PropertyDefinition
  1. propNamePropertyDefinitionPropName
  2. 如果 propNameempty,返回新的空列表
  3. 返回 « propName »。
PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. listPropertyDefinitionListPropertyNameList
  2. propNamePropertyDefinitionPropName
  3. 如果 propNameempty,返回 list
  4. 返回 list 和 « propName » 的列表连接

13.2.5.4 运行时语义:Evaluation

ObjectLiteral : { }
  1. 返回 OrdinaryObjectCreate(%Object.prototype%)。
ObjectLiteral : { PropertyDefinitionList } { PropertyDefinitionList , }
  1. objOrdinaryObjectCreate(%Object.prototype%)。
  2. 执行 ? PropertyDefinitionList 与参数 objPropertyDefinitionEvaluation
  3. 返回 obj
LiteralPropertyName : IdentifierName
  1. 返回 IdentifierNameStringValue
LiteralPropertyName : StringLiteral
  1. 返回 StringLiteralSV
LiteralPropertyName : NumericLiteral
  1. nbrNumericLiteralNumericValue
  2. 返回 ! ToString(nbr)。
ComputedPropertyName : [ AssignmentExpression ]
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. propName 为 ? GetValue(exprValue)。
  3. 返回 ? ToPropertyKey(propName)。

13.2.5.5 运行时语义:PropertyDefinitionEvaluation

语法导向操作 PropertyDefinitionEvaluation 接受参数 object(一个对象)并返回包含 unused正常完成突然完成。它在以下产生式上分段定义:

PropertyDefinitionList : PropertyDefinitionList , PropertyDefinition
  1. 执行 ? PropertyDefinitionList 与参数 objectPropertyDefinitionEvaluation
  2. 执行 ? PropertyDefinition 与参数 objectPropertyDefinitionEvaluation
  3. 返回 unused
PropertyDefinition : ... AssignmentExpression
  1. exprValue 为 ? AssignmentExpressionEvaluation
  2. fromValue 为 ? GetValue(exprValue)。
  3. excludedNames 为新的空列表
  4. 执行 ? CopyDataProperties(object, fromValue, excludedNames)。
  5. 返回 unused
PropertyDefinition : IdentifierReference
  1. propNameIdentifierReferenceStringValue
  2. exprValue 为 ? IdentifierReferenceEvaluation
  3. propValue 为 ? GetValue(exprValue)。
  4. 断言object 是一个普通的、可扩展的、没有不可配置属性的对象。
  5. 执行 ! CreateDataPropertyOrThrow(object, propName, propValue)。
  6. 返回 unused
PropertyDefinition : PropertyName : AssignmentExpression
  1. propKey 为 ? PropertyNameEvaluation
  2. 如果此 PropertyDefinition 包含在正在为 ParseJSON 求值的 Script 中(参见 ParseJSON 的步骤 6),则
    1. isProtoSetterfalse
  3. 否则,如果 propKey"__proto__" 并且 PropertyNameIsComputedPropertyKeyfalse,则
    1. isProtoSettertrue
  4. 否则,
    1. isProtoSetterfalse
  5. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true 并且 isProtoSetterfalse,则
    1. propValue 为 ? AssignmentExpression 与参数 propKeyNamedEvaluation
  6. 否则,
    1. exprValueRef 为 ? AssignmentExpressionEvaluation
    2. propValue 为 ? GetValue(exprValueRef)。
  7. 如果 isProtoSettertrue,则
    1. 如果 propValue 是对象propValuenull,则
      1. 执行 ! object.[[SetPrototypeOf]](propValue)。
    2. 返回 unused
  8. 断言object 是一个普通的、可扩展的、没有不可配置属性的对象。
  9. 执行 ! CreateDataPropertyOrThrow(object, propKey, propValue)。
  10. 返回 unused
PropertyDefinition : MethodDefinition
  1. 执行 ? MethodDefinition 与参数 objecttrueMethodDefinitionEvaluation
  2. 返回 unused

13.2.6 函数定义表达式

有关 PrimaryExpression : FunctionExpression ,参见 15.2

有关 PrimaryExpression : GeneratorExpression ,参见 15.5

有关 PrimaryExpression : ClassExpression ,参见 15.7

有关 PrimaryExpression : AsyncFunctionExpression ,参见 15.8

有关 PrimaryExpression : AsyncGeneratorExpression ,参见 15.6

13.2.7 正则表达式字面量

语法

参见 12.9.5

13.2.7.1 静态语义:早期错误

PrimaryExpression : RegularExpressionLiteral

13.2.7.2 静态语义:IsValidRegularExpressionLiteral ( literal )

抽象操作 IsValidRegularExpressionLiteral 接受参数 literal(一个 RegularExpressionLiteral 解析节点)并返回布尔值。它确定其参数是否是有效的正则表达式字面量。调用时执行以下步骤:

  1. flagsliteralFlagText
  2. 如果 flags 包含除 dgimsuvy 之外的任何码点,或者如果 flags 包含任何码点超过一次,返回 false
  3. 如果 flags 包含 u,令 utrue;否则令 ufalse
  4. 如果 flags 包含 v,令 vtrue;否则令 vfalse
  5. patternTextliteralBodyText
  6. 如果 ufalsevfalse,则
    1. stringValueCodePointsToString(patternText)。
    2. 设置 patternText 为通过将 stringValue 的每个 16 位元素解释为 Unicode BMP 码点而产生的码点序列。UTF-16 解码不应用于这些元素。
  7. parseResultParsePattern(patternText, u, v)。
  8. 如果 parseResult解析节点,返回 true;否则返回 false

13.2.7.3 运行时语义:Evaluation

PrimaryExpression : RegularExpressionLiteral
  1. patternCodePointsToString(RegularExpressionLiteralBodyText)。
  2. flagsCodePointsToString(RegularExpressionLiteralFlagText)。
  3. 返回 ! RegExpCreate(pattern, flags)。

13.2.8 模板字面量

语法

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.1 静态语义:早期错误

TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate TemplateLiteral[Yield, Await, Tagged] : SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await]

13.2.8.2 静态语义:TemplateStrings

语法导向操作 TemplateStrings 接受参数 raw(布尔值)并返回字符串或 undefined列表。它在以下产生式上分段定义:

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 « TemplateString(NoSubstitutionTemplate, raw) »。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. head 为 « TemplateString(TemplateHead, raw) »。
  2. tailTemplateSpans 使用参数 rawTemplateStrings
  3. 返回 headtail列表连接
TemplateSpans : TemplateTail
  1. 返回 « TemplateString(TemplateTail, raw) »。
TemplateSpans : TemplateMiddleList TemplateTail
  1. middleTemplateMiddleList 使用参数 rawTemplateStrings
  2. tail 为 « TemplateString(TemplateTail, raw) »。
  3. 返回 middletail列表连接
TemplateMiddleList : TemplateMiddle Expression
  1. 返回 « TemplateString(TemplateMiddle, raw) »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. frontTemplateMiddleList 使用参数 rawTemplateStrings
  2. last 为 « TemplateString(TemplateMiddle, raw) »。
  3. 返回 frontlast列表连接

13.2.8.3 静态语义:TemplateString ( templateToken, raw )

抽象操作 TemplateString 接受参数 templateToken(一个 NoSubstitutionTemplate 解析节点TemplateHead 解析节点TemplateMiddle 解析节点,或 TemplateTail 解析节点)和 raw(布尔值)并返回字符串或 undefined。调用时执行以下步骤:

  1. 如果 rawtrue,则
    1. stringtemplateTokenTRV
  2. 否则,
    1. stringtemplateTokenTV
  3. 返回 string

如果 rawfalsetemplateToken 包含 NotEscapeSequence,此操作返回 undefined。在所有其他情况下,它返回字符串。

13.2.8.4 GetTemplateObject ( templateLiteral )

抽象操作 GetTemplateObject 接受参数 templateLiteral(一个解析节点)并返回数组。调用时执行以下步骤:

  1. realm当前领域记录
  2. templateRegistryrealm.[[TemplateMap]]
  3. 对于 templateRegistry 的每个元素 e,执行
    1. 如果 e.[[Site]]templateLiteral同一个解析节点,则
      1. 返回 e.[[Array]]
  4. rawStringstemplateLiteral 使用参数 trueTemplateStrings
  5. 断言rawStrings 是字符串的列表
  6. cookedStringstemplateLiteral 使用参数 falseTemplateStrings
  7. count列表 cookedStrings 中的元素数量。
  8. 断言count ≤ 232 - 1。
  9. template 为 ! ArrayCreate(count)。
  10. rawObj 为 ! ArrayCreate(count)。
  11. index 为 0。
  12. 重复,当 index < count 时,
    1. prop 为 ! ToString(𝔽(index))。
    2. cookedValuecookedStrings[index]。
    3. 执行 ! DefinePropertyOrThrow(template, prop, PropertyDescriptor { [[Value]]: cookedValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    4. rawValue 为字符串值 rawStrings[index]。
    5. 执行 ! DefinePropertyOrThrow(rawObj, prop, PropertyDescriptor { [[Value]]: rawValue, [[Writable]]: false, [[Enumerable]]: true, [[Configurable]]: false })。
    6. 设置 indexindex + 1。
  13. 执行 ! SetIntegrityLevel(rawObj, frozen)。
  14. 执行 ! DefinePropertyOrThrow(template, "raw", PropertyDescriptor { [[Value]]: rawObj, [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false })。
  15. 执行 ! SetIntegrityLevel(template, frozen)。
  16. 记录 { [[Site]]: templateLiteral, [[Array]]: template } 附加到 realm.[[TemplateMap]]
  17. 返回 template
注 1

模板对象的创建不能导致突然完成

注 2

领域程序代码中的每个 TemplateLiteral 都与一个唯一的模板对象相关联,该对象用于带标签模板的求值(13.2.8.6)。模板对象被冻结,每次求值特定带标签模板时都使用相同的模板对象。模板对象是在首次求值 TemplateLiteral 时惰性创建,还是在首次求值前急切创建,是实现选择,ECMAScript 代码无法观察到。

注 3

本规范的未来版本可能定义模板对象的附加不可枚举属性。

13.2.8.5 运行时语义:SubstitutionEvaluation

语法导向操作 SubstitutionEvaluation 不接受参数并返回包含 ECMAScript 语言值列表正常完成突然完成。它在以下产生式上分段定义:

TemplateSpans : TemplateTail
  1. 返回新的空列表
TemplateSpans : TemplateMiddleList TemplateTail
  1. 返回 ? TemplateMiddleListSubstitutionEvaluation
TemplateMiddleList : TemplateMiddle Expression
  1. subRef 为 ? ExpressionEvaluation
  2. sub 为 ? GetValue(subRef)。
  3. 返回 « sub »。
TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. preceding 为 ? TemplateMiddleListSubstitutionEvaluation
  2. nextRef 为 ? ExpressionEvaluation
  3. next 为 ? GetValue(nextRef)。
  4. 返回 preceding 和 « next » 的列表连接

13.2.8.6 运行时语义:Evaluation

TemplateLiteral : NoSubstitutionTemplate
  1. 返回 NoSubstitutionTemplateTV,如 12.9.6 中定义。
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. headTemplateHeadTV,如 12.9.6 中定义。
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. tail 为 ? TemplateSpansEvaluation
  6. 返回 headmiddletail字符串连接
注 1

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

TemplateSpans : TemplateTail
  1. 返回 TemplateTailTV,如 12.9.6 中定义。
TemplateSpans : TemplateMiddleList TemplateTail
  1. head 为 ? TemplateMiddleListEvaluation
  2. tailTemplateTailTV,如 12.9.6 中定义。
  3. 返回 headtail字符串连接
TemplateMiddleList : TemplateMiddle Expression
  1. headTemplateMiddleTV,如 12.9.6 中定义。
  2. subRef 为 ? ExpressionEvaluation
  3. sub 为 ? GetValue(subRef)。
  4. middle 为 ? ToString(sub)。
  5. 返回 headmiddle字符串连接
注 2

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

TemplateMiddleList : TemplateMiddleList TemplateMiddle Expression
  1. rest 为 ? TemplateMiddleListEvaluation
  2. middleTemplateMiddleTV,如 12.9.6 中定义。
  3. subRef 为 ? ExpressionEvaluation
  4. sub 为 ? GetValue(subRef)。
  5. last 为 ? ToString(sub)。
  6. 返回 restmiddlelast字符串连接
注 3

应用于 Expression 值的字符串转换语义类似于 String.prototype.concat 而不是 + 运算符。

13.2.9 分组运算符

13.2.9.1 静态语义:早期错误

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList

13.2.9.2 运行时语义:Evaluation

PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 ? exprEvaluation
ParenthesizedExpression : ( Expression )
  1. 返回 ? ExpressionEvaluation。这可能是引用类型。

此算法不对 ExpressionEvaluation 应用 GetValue。这样做的主要动机是使 deletetypeof 等运算符可以应用于带括号的表达式。

13.3 左值表达式

语法

MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await]

补充语法

当处理产生式的实例时
CallExpression : CoverCallExpressionAndAsyncArrowHead
使用以下语法细化对 CoverCallExpressionAndAsyncArrowHead 的解释:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

13.3.1 静态语义

13.3.1.1 静态语义:早期错误

OptionalChain : ?. TemplateLiteral OptionalChain TemplateLiteral
  • 如果任何源文本与此产生式匹配,则是语法错误。

此产生式的存在是为了防止自动分号插入规则(12.10)应用于以下代码:

a?.b
`c`

这样它就不会被解释为两个有效的语句。目的是与没有可选链的类似代码保持一致:

a.b
`c`

这是一个有效的语句,其中不应用自动分号插入。

ImportMeta : import . meta

13.3.2 属性访问器

属性通过名称进行访问,可以使用点记法:

或括号记法:

点记法通过以下语法转换解释:

在行为上等同于

MemberExpression [ <identifier-name-string> ]

同样地

在行为上等同于

CallExpression [ <identifier-name-string> ]

其中 <identifier-name-string> 是 IdentifierNameStringValue

13.3.2.1 运行时语义:Evaluation

MemberExpression : MemberExpression [ Expression ]
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 MemberExpressionIsStrict
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
MemberExpression : MemberExpression . IdentifierName
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 MemberExpressionIsStrict
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
MemberExpression : MemberExpression . PrivateIdentifier
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。
CallExpression : CallExpression [ Expression ]
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 CallExpressionIsStrict
  4. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
CallExpression : CallExpression . IdentifierName
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. strict 为此 CallExpressionIsStrict
  4. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
CallExpression : CallExpression . PrivateIdentifier
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. fieldNameStringPrivateIdentifierStringValue
  4. 返回 MakePrivateReference(baseValue, fieldNameString)。

13.3.3 EvaluatePropertyAccessWithExpressionKey ( baseValue, expression, strict )

抽象操作 EvaluatePropertyAccessWithExpressionKey 接受参数 baseValue(一个 ECMAScript 语言值)、 expression(一个 Expression 解析节点)和 strict(一个布尔值),返回包含 引用记录正常完成突然完成。当调用时执行以下步骤:

  1. propertyNameReference 为 ? expressionEvaluation
  2. propertyNameValue 为 ? GetValue(propertyNameReference)。
  3. 注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对 propertyNameValue 执行。但是,在 a[b] = c 的情况下,它将直到 c 求值之后才执行。
  4. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyNameValue, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.4 EvaluatePropertyAccessWithIdentifierKey ( baseValue, identifierName, strict )

抽象操作 EvaluatePropertyAccessWithIdentifierKey 接受参数 baseValue(一个 ECMAScript 语言值)、 identifierName(一个 IdentifierName 解析节点)和 strict(一个布尔值),返回一个 引用记录。当调用时执行以下步骤:

  1. propertyNameStringidentifierNameStringValue
  2. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyNameString, [[Strict]]: strict, [[ThisValue]]: empty }。

13.3.5 new 运算符

13.3.5.1 运行时语义:Evaluation

NewExpression : new NewExpression
  1. 返回 ? EvaluateNew(NewExpression, empty)。
MemberExpression : new MemberExpression Arguments
  1. 返回 ? EvaluateNew(MemberExpression, Arguments)。

13.3.5.1.1 EvaluateNew ( constructExpr, arguments )

抽象操作 EvaluateNew 接受参数 constructExpr(一个 NewExpression 解析节点或一个 MemberExpression 解析节点)和 argumentsempty 或一个 Arguments 解析节点),返回包含 ECMAScript 语言值正常完成突然完成。当调用时执行以下步骤:

  1. ref 为 ? constructExprEvaluation
  2. constructor 为 ? GetValue(ref)。
  3. 如果 argumentsempty,则
    1. argList 为新的空列表
  4. 否则,
    1. argList 为 ? argumentsArgumentListEvaluation
  5. 如果 IsConstructor(constructor) 是 false,抛出 TypeError 异常。
  6. 返回 ? Construct(constructor, argList)。

13.3.6 函数调用

13.3.6.1 运行时语义:Evaluation

CallExpression : CoverCallExpressionAndAsyncArrowHead
  1. expr 为被 CoverCallExpressionAndAsyncArrowHead 覆盖CallMemberExpression
  2. memberExprexprMemberExpression
  3. argumentsexprArguments
  4. ref 为 ? memberExprEvaluation
  5. func 为 ? GetValue(ref)。
  6. 如果 ref引用记录IsPropertyReference(ref) 是 false,且 ref.[[ReferencedName]]"eval",则
    1. 如果 SameValue(func, %eval%) 是 true,则
      1. argList 为 ? argumentsArgumentListEvaluation
      2. 如果 argList 没有元素,返回 undefined
      3. evalArgargList 的第一个元素。
      4. 如果此 CallExpressionIsStricttrue,则令 strictCallertrue。否则令 strictCallerfalse
      5. 返回 ? PerformEval(evalArg, strictCaller, true)。
  7. thisCall 为此 CallExpression
  8. tailCallIsInTailPosition(thisCall)。
  9. 返回 ? EvaluateCall(func, ref, arguments, tailCall)。

执行步骤 6.a.vCallExpression 求值是直接 eval

CallExpression : CallExpression Arguments
  1. ref 为 ? CallExpressionEvaluation
  2. func 为 ? GetValue(ref)。
  3. thisCall 为此 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(func, ref, Arguments, tailCall)。

13.3.6.2 EvaluateCall ( func, ref, arguments, tailPosition )

抽象操作 EvaluateCall 接受参数 func(一个 ECMAScript 语言值)、 ref(一个 ECMAScript 语言值引用记录)、 arguments(一个 解析节点)和 tailPosition(一个布尔值),返回包含 ECMAScript 语言值正常完成突然完成。当调用时执行以下步骤:

  1. 如果 ref引用记录,则
    1. 如果 IsPropertyReference(ref) 是 true,则
      1. thisValueGetThisValue(ref)。
    2. 否则,
      1. refEnvref.[[Base]]
      2. 断言refEnv环境记录
      3. thisValuerefEnv.WithBaseObject()。
  2. 否则,
    1. thisValueundefined
  3. argList 为 ? argumentsArgumentListEvaluation
  4. 如果 func 不是对象,抛出 TypeError 异常。
  5. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  6. 如果 tailPositiontrue,执行 PrepareForTailCall()。
  7. 返回 ? Call(func, thisValue, argList)。

13.3.7 super 关键字

13.3.7.1 运行时语义:Evaluation

SuperProperty : super [ Expression ]
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyNameReference 为 ? ExpressionEvaluation
  4. propertyNameValue 为 ? GetValue(propertyNameReference)。
  5. strict 为此 SuperPropertyIsStrict
  6. 注:在大多数情况下,ToPropertyKey 将在此步骤之后立即对 propertyNameValue 执行。但是,在 super[b] = c 的情况下,它将直到 c 求值之后才执行。
  7. 返回 MakeSuperPropertyReference(actualThis, propertyNameValue, strict)。
SuperProperty : super . IdentifierName
  1. envGetThisEnvironment()。
  2. actualThis 为 ? env.GetThisBinding()。
  3. propertyKeyIdentifierNameStringValue
  4. strict 为此 SuperPropertyIsStrict
  5. 返回 MakeSuperPropertyReference(actualThis, propertyKey, strict)。
SuperCall : super Arguments
  1. newTargetGetNewTarget()。
  2. 断言newTarget构造器
  3. funcGetSuperConstructor()。
  4. argList 为 ? ArgumentsArgumentListEvaluation
  5. 如果 IsConstructor(func) 是 false,抛出 TypeError 异常。
  6. result 为 ? Construct(func, argList, newTarget)。
  7. thisERGetThisEnvironment()。
  8. 断言thisER函数环境记录
  9. 执行 ? BindThisValue(thisER, result)。
  10. FthisER.[[FunctionObject]]
  11. 断言F 是 ECMAScript 函数对象
  12. 执行 ? InitializeInstanceElements(result, F)。
  13. 返回 result

13.3.7.2 GetSuperConstructor ( )

抽象操作 GetSuperConstructor 不接受参数,返回一个 ECMAScript 语言值。当调用时执行以下步骤:

  1. envRecGetThisEnvironment()。
  2. 断言envRec函数环境记录
  3. activeFunctionenvRec.[[FunctionObject]]
  4. 断言activeFunction 是 ECMAScript 函数对象
  5. superConstructor 为 ! activeFunction.[[GetPrototypeOf]]()。
  6. 返回 superConstructor

13.3.7.3 MakeSuperPropertyReference ( actualThis, propertyKey, strict )

抽象操作 MakeSuperPropertyReference 接受参数 actualThis(一个 ECMAScript 语言值)、 propertyKey(一个 ECMAScript 语言值)和 strict(一个布尔值),返回一个 Super 引用记录。当调用时执行以下步骤:

  1. envGetThisEnvironment()。
  2. 断言env.HasSuperBinding() 是 true
  3. 断言env函数环境记录
  4. baseValueGetSuperBase(env)。
  5. 返回引用记录 { [[Base]]: baseValue, [[ReferencedName]]: propertyKey, [[Strict]]: strict, [[ThisValue]]: actualThis }。

13.3.8 参数列表

参数列表的求值产生一个值的 列表

13.3.8.1 运行时语义:ArgumentListEvaluation

语法制导操作 ArgumentListEvaluation 不接受参数,返回包含 ECMAScript 语言值列表正常完成突然完成。它在以下产生式上分段定义:

Arguments : ( )
  1. 返回新的空列表
ArgumentList : AssignmentExpression
  1. ref 为 ? AssignmentExpressionEvaluation
  2. arg 为 ? GetValue(ref)。
  3. 返回 « arg »。
ArgumentList : ... AssignmentExpression
  1. list 为新的空列表
  2. spreadRef 为 ? AssignmentExpressionEvaluation
  3. spreadObj 为 ? GetValue(spreadRef)。
  4. iteratorRecord 为 ? GetIterator(spreadObj, sync)。
  5. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 list
    3. next 附加到 list
ArgumentList : ArgumentList , AssignmentExpression
  1. precedingArgs 为 ? ArgumentListArgumentListEvaluation
  2. ref 为 ? AssignmentExpressionEvaluation
  3. arg 为 ? GetValue(ref)。
  4. 返回 precedingArgs 和 « arg » 的列表连接
ArgumentList : ArgumentList , ... AssignmentExpression
  1. precedingArgs 为 ? ArgumentListArgumentListEvaluation
  2. spreadRef 为 ? AssignmentExpressionEvaluation
  3. iteratorRecord 为 ? GetIterator(? GetValue(spreadRef), sync)。
  4. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 precedingArgs
    3. next 附加到 precedingArgs
TemplateLiteral : NoSubstitutionTemplate
  1. templateLiteral 为此 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. 返回 « siteObj »。
TemplateLiteral : SubstitutionTemplate
  1. templateLiteral 为此 TemplateLiteral
  2. siteObjGetTemplateObject(templateLiteral)。
  3. remaining 为 ? SubstitutionTemplateArgumentListEvaluation
  4. 返回 « siteObj » 和 remaining列表连接
SubstitutionTemplate : TemplateHead Expression TemplateSpans
  1. firstSubRef 为 ? ExpressionEvaluation
  2. firstSub 为 ? GetValue(firstSubRef)。
  3. restSub 为 ? TemplateSpansSubstitutionEvaluation
  4. 断言restSub 是可能为空的列表
  5. 返回 « firstSub » 和 restSub列表连接

13.3.9 可选链

可选链是一个或多个属性访问和函数调用的链,其中第一个以标记 ?. 开始。

13.3.9.1 运行时语义:Evaluation

OptionalExpression : MemberExpression OptionalChain
  1. baseReference 为 ? MemberExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation
OptionalExpression : CallExpression OptionalChain
  1. baseReference 为 ? CallExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation
OptionalExpression : OptionalExpression OptionalChain
  1. baseReference 为 ? OptionalExpressionEvaluation
  2. baseValue 为 ? GetValue(baseReference)。
  3. 如果 baseValueundefinednull,则
    1. 返回 undefined
  4. 返回 ? OptionalChainbaseValuebaseReference 为参数的 ChainEvaluation

13.3.9.2 运行时语义:ChainEvaluation

语法制导操作 ChainEvaluation 接受参数 baseValue(一个 ECMAScript 语言值)和 baseReference(一个 ECMAScript 语言值引用记录),返回包含 ECMAScript 语言值引用记录正常完成,或突然完成。它在以下产生式上分段定义:

OptionalChain : ?. Arguments
  1. thisChain 为此 OptionalChain
  2. tailCallIsInTailPosition(thisChain)。
  3. 返回 ? EvaluateCall(baseValue, baseReference, Arguments, tailCall)。
OptionalChain : ?. [ Expression ]
  1. strict 为此 OptionalChainIsStrict
  2. 返回 ? EvaluatePropertyAccessWithExpressionKey(baseValue, Expression, strict)。
OptionalChain : ?. IdentifierName
  1. strict 为此 OptionalChainIsStrict
  2. 返回 EvaluatePropertyAccessWithIdentifierKey(baseValue, IdentifierName, strict)。
OptionalChain : ?. PrivateIdentifier
  1. fieldNameStringPrivateIdentifierStringValue
  2. 返回 MakePrivateReference(baseValue, fieldNameString)。
OptionalChain : OptionalChain Arguments
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. thisChain 为此 OptionalChain
  5. tailCallIsInTailPosition(thisChain)。
  6. 返回 ? EvaluateCall(newValue, newReference, Arguments, tailCall)。
OptionalChain : OptionalChain [ Expression ]
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. strict 为此 OptionalChainIsStrict
  5. 返回 ? EvaluatePropertyAccessWithExpressionKey(newValue, Expression, strict)。
OptionalChain : OptionalChain . IdentifierName
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. strict 为此 OptionalChainIsStrict
  5. 返回 EvaluatePropertyAccessWithIdentifierKey(newValue, IdentifierName, strict)。
OptionalChain : OptionalChain . PrivateIdentifier
  1. optionalChainOptionalChain
  2. newReference 为 ? optionalChainbaseValuebaseReference 为参数的 ChainEvaluation
  3. newValue 为 ? GetValue(newReference)。
  4. fieldNameStringPrivateIdentifierStringValue
  5. 返回 MakePrivateReference(newValue, fieldNameString)。

13.3.10 Import 调用

13.3.10.1 运行时语义:Evaluation

ImportCall : import ( AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(AssignmentExpression)。
ImportCall : import ( AssignmentExpression , AssignmentExpression ,opt )
  1. 返回 ? EvaluateImportCall(第一个 AssignmentExpression, 第二个 AssignmentExpression)。

13.3.10.2 EvaluateImportCall ( specifierExpression [ , optionsExpression ] )

抽象操作 EvaluateImportCall 接受参数 specifierExpression(一个 解析节点)和可选参数 optionsExpression(一个 解析节点),返回包含 Promise 的正常完成突然完成。当调用时执行以下步骤:

  1. referrerGetActiveScriptOrModule()。
  2. 如果 referrernull,设置 referrer当前 Realm 记录
  3. specifierRef 为 ? specifierExpressionEvaluation
  4. specifier 为 ? GetValue(specifierRef)。
  5. 如果 optionsExpression 存在,则
    1. optionsRef 为 ? optionsExpressionEvaluation
    2. options 为 ? GetValue(optionsRef)。
  6. 否则,
    1. optionsundefined
  7. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  8. specifierStringCompletion(ToString(specifier))。
  9. IfAbruptRejectPromise(specifierString, promiseCapability)。
  10. attributes 为新的空列表
  11. 如果 options 不是 undefined,则
    1. 如果 options 不是对象,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    2. attributesObjCompletion(Get(options, "with"))。
    3. IfAbruptRejectPromise(attributesObj, promiseCapability)。
    4. 如果 attributesObj 不是 undefined,则
      1. 如果 attributesObj 不是对象,则
        1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
        2. 返回 promiseCapability.[[Promise]]
      2. entriesCompletion(EnumerableOwnProperties(attributesObj, key+value))。
      3. IfAbruptRejectPromise(entries, promiseCapability)。
      4. 对于 entries 的每个元素 entry,执行
        1. key 为 ! Get(entry, "0")。
        2. value 为 ! Get(entry, "1")。
        3. 如果 key 是字符串,则
          1. 如果 value 不是字符串,则
            1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
            2. 返回 promiseCapability.[[Promise]]
          2. ImportAttribute 记录 { [[Key]]: key, [[Value]]: value } 附加到 attributes
    5. 如果 AllImportAttributesSupported(attributes) 是 false,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « 新创建的 TypeError 对象 »)。
      2. 返回 promiseCapability.[[Promise]]
    6. 按照其 [[Key]] 字段的字典序对 attributes 进行排序,将每个此类字段的值视为 UTF-16 代码单元值的序列。注:此排序仅在禁止宿主基于属性枚举的顺序改变行为这一点上是可观察的。
  12. moduleRequest 为新的ModuleRequest 记录 { [[Specifier]]: specifierString, [[Attributes]]: attributes }。
  13. 执行 HostLoadImportedModule(referrer, moduleRequest, empty, promiseCapability)。
  14. 返回 promiseCapability.[[Promise]]

13.3.10.3 ContinueDynamicImport ( promiseCapability, moduleCompletion )

抽象操作 ContinueDynamicImport 接受参数 promiseCapability(一个 PromiseCapability 记录)和 moduleCompletion包含 模块记录正常完成抛出完成),返回 unused。它完成最初由 import() 调用开始的动态导入过程,适当地解决或拒绝由该调用返回的 promise。当调用时执行以下步骤:

  1. 如果 moduleCompletion突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
    2. 返回 unused
  2. modulemoduleCompletion.[[Value]]
  3. loadPromisemodule.LoadRequestedModules()。
  4. rejectedClosure 为新的抽象闭包,参数为 (reason),捕获 promiseCapability 并在调用时执行以下步骤:
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « reason »)。
    2. 返回 unused
  5. onRejectedCreateBuiltinFunction(rejectedClosure, 1, "", « »)。
  6. linkAndEvaluateClosure 为新的抽象闭包,无参数,捕获 modulepromiseCapabilityonRejected 并在调用时执行以下步骤:
    1. linkCompletion(module.Link())。
    2. 如果 link突然完成,则
      1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « link.[[Value]] »)。
      2. 返回 unused
    3. evaluatePromisemodule.Evaluate()。
    4. fulfilledClosure 为新的抽象闭包,无参数,捕获 modulepromiseCapability 并在调用时执行以下步骤:
      1. namespaceGetModuleNamespace(module)。
      2. 执行 ! Call(promiseCapability.[[Resolve]], undefined, « namespace »)。
      3. 返回 unused
    5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
    6. 执行 PerformPromiseThen(evaluatePromise, onFulfilled, onRejected)。
    7. 返回 unused
  7. linkAndEvaluateCreateBuiltinFunction(linkAndEvaluateClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(loadPromise, linkAndEvaluate, onRejected)。
  9. 返回 unused

13.3.11 标记模板

标记模板是一个函数调用,其中调用的参数来源于 TemplateLiteral (13.2.8)。实际参数包括模板对象(13.2.8.4)和通过求值嵌入在 TemplateLiteral 中的表达式产生的值。

13.3.11.1 运行时语义:Evaluation

MemberExpression : MemberExpression TemplateLiteral
  1. tagRef 为 ? MemberExpressionEvaluation
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为此 MemberExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。
CallExpression : CallExpression TemplateLiteral
  1. tagRef 为 ? CallExpressionEvaluation
  2. tagFunc 为 ? GetValue(tagRef)。
  3. thisCall 为此 CallExpression
  4. tailCallIsInTailPosition(thisCall)。
  5. 返回 ? EvaluateCall(tagFunc, tagRef, TemplateLiteral, tailCall)。

13.3.12 元属性

13.3.12.1 运行时语义:Evaluation

NewTarget : new . target
  1. 返回 GetNewTarget()。
ImportMeta : import . meta
  1. moduleGetActiveScriptOrModule()。
  2. 断言module源文本模块记录
  3. importMetamodule.[[ImportMeta]]
  4. 如果 importMetaempty,则
    1. 设置 importMetaOrdinaryObjectCreate(null)。
    2. importMetaValuesHostGetImportMetaProperties(module)。
    3. 对于 importMetaValues 的每个记录 { [[Key]], [[Value]] } p,执行
      1. 执行 ! CreateDataPropertyOrThrow(importMeta, p.[[Key]], p.[[Value]])。
    4. 执行 HostFinalizeImportMeta(importMeta, module)。
    5. 设置 module.[[ImportMeta]]importMeta
    6. 返回 importMeta
  5. 否则,
    1. 断言importMeta 是对象
    2. 返回 importMeta

13.3.12.1.1 HostGetImportMetaProperties ( moduleRecord )

宿主定义的抽象操作 HostGetImportMetaProperties 接受参数 moduleRecord(一个模块记录),返回包含字段 [[Key]](一个属性键)和 [[Value]](一个ECMAScript 语言值)的记录列表。它允许宿主为从 import.meta 返回的对象提供属性键和值。

HostGetImportMetaProperties 的默认实现是返回新的空列表

13.3.12.1.2 HostFinalizeImportMeta ( importMeta, moduleRecord )

宿主定义的抽象操作 HostFinalizeImportMeta 接受参数 importMeta(一个对象)和 moduleRecord(一个模块记录),返回 unused。它允许宿主执行任何特殊操作来准备从 import.meta 返回的对象。

大多数宿主只需简单地定义 HostGetImportMetaProperties,并保持 HostFinalizeImportMeta 的默认行为。然而,HostFinalizeImportMeta 为需要在对象暴露给 ECMAScript 代码之前直接操作对象的宿主提供了"紧急出口"。

HostFinalizeImportMeta 的默认实现是返回 unused

13.4 更新表达式

语法

UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await]

13.4.1 静态语义:早期错误

UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- UpdateExpression : ++ UnaryExpression -- UnaryExpression

13.4.2 后缀递增运算符

13.4.2.1 运行时语义:Evaluation

UpdateExpression : LeftHandSideExpression ++
  1. lhs 为 ? LeftHandSideExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::add(oldValue, 1)。
  5. 执行 ? PutValue(lhs, newValue)。
  6. 返回 oldValue

13.4.3 后缀递减运算符

13.4.3.1 运行时语义:Evaluation

UpdateExpression : LeftHandSideExpression --
  1. lhs 为 ? LeftHandSideExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(lhs))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::subtract(oldValue, 1)。
  5. 执行 ? PutValue(lhs, newValue)。
  6. 返回 oldValue

13.4.4 前缀递增运算符

13.4.4.1 运行时语义:Evaluation

UpdateExpression : ++ UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::add(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::add(oldValue, 1)。
  5. 执行 ? PutValue(expr, newValue)。
  6. 返回 newValue

13.4.5 前缀递减运算符

13.4.5.1 运行时语义:Evaluation

UpdateExpression : -- UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. newValueNumber::subtract(oldValue, 1𝔽)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. newValueBigInt::subtract(oldValue, 1)。
  5. 执行 ? PutValue(expr, newValue)。
  6. 返回 newValue

13.5 一元运算符

语法

UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield]

13.5.1 delete 运算符

13.5.1.1 静态语义:早期错误

UnaryExpression : delete UnaryExpression

最后一条规则意味着如 delete (((foo))) 这样的表达式由于第一条规则的递归应用而产生早期错误

13.5.1.2 运行时语义:Evaluation

UnaryExpression : delete UnaryExpression
  1. ref 为 ? UnaryExpressionEvaluation
  2. 如果 ref 不是引用记录,返回 true
  3. 如果 IsUnresolvableReference(ref) 是 true,则
    1. 断言ref.[[Strict]]false
    2. 返回 true
  4. 如果 IsPropertyReference(ref) 是 true,则
    1. 断言IsPrivateReference(ref) 是 false
    2. 如果 IsSuperReference(ref) 是 true,抛出 ReferenceError 异常。
    3. baseObj 为 ? ToObject(ref.[[Base]])。
    4. 如果 ref.[[ReferencedName]] 不是属性键,则
      1. 设置 ref.[[ReferencedName]] 为 ? ToPropertyKey(ref.[[ReferencedName]])。
    5. deleteStatus 为 ? baseObj.[[Delete]](ref.[[ReferencedName]])。
    6. 如果 deleteStatusfalse 并且 ref.[[Strict]]true,抛出 TypeError 异常。
    7. 返回 deleteStatus
  5. 否则,
    1. baseref.[[Base]]
    2. 断言base环境记录
    3. 返回 ? base.DeleteBinding(ref.[[ReferencedName]])。
注 1

delete 运算符出现在严格模式代码中时,如果其 UnaryExpression 是对变量、函数参数或函数名的直接引用,则抛出 SyntaxError 异常。此外,如果 delete 运算符出现在严格模式代码中并且要删除的属性具有属性 { [[Configurable]]: false }(或者无法删除),则抛出 TypeError 异常。

注 2

可能在步骤 4.c 中创建的对象在上述抽象操作和普通对象 [[Delete]] 内部方法之外是不可访问的。实现可能选择避免实际创建该对象。

13.5.2 void 运算符

13.5.2.1 运行时语义:Evaluation

UnaryExpression : void UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 执行 ? GetValue(expr)。
  3. 返回 undefined

即使不使用 GetValue 的值,也必须调用它,因为它可能有可观察的副作用。

13.5.3 typeof 运算符

13.5.3.1 运行时语义:Evaluation

UnaryExpression : typeof UnaryExpression
  1. val 为 ? UnaryExpressionEvaluation
  2. 如果 val引用记录,则
    1. 如果 IsUnresolvableReference(val) 是 true,返回 "undefined"
  3. 设置 val 为 ? GetValue(val)。
  4. 如果 valundefined,返回 "undefined"
  5. 如果 valnull,返回 "object"
  6. 如果 val 是字符串,返回 "string"
  7. 如果 val 是符号,返回 "symbol"
  8. 如果 val 是布尔值,返回 "boolean"
  9. 如果 val 是数字,返回 "number"
  10. 如果 val 是 BigInt,返回 "bigint"
  11. 断言val 是对象
  12. 注:此步骤在 B.3.6.3 节中被替换。
  13. 如果 val 具有 [[Call]] 内部槽,返回 "function"
  14. 返回 "object"

13.5.4 一元 + 运算符

一元 + 运算符将其操作数转换为数字类型

13.5.4.1 运行时语义:Evaluation

UnaryExpression : + UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. 返回 ? ToNumber(? GetValue(expr))。

13.5.5 一元 - 运算符

一元 - 运算符将其操作数转换为数值然后对其取反。对 +0𝔽 取反产生 -0𝔽,对 -0𝔽 取反产生 +0𝔽

13.5.5.1 运行时语义:Evaluation

UnaryExpression : - UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. 返回 Number::unaryMinus(oldValue)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. 返回 BigInt::unaryMinus(oldValue)。

13.5.6 按位非运算符(~

13.5.6.1 运行时语义:Evaluation

UnaryExpression : ~ UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValue 为 ? ToNumeric(? GetValue(expr))。
  3. 如果 oldValue 是数字,则
    1. 返回 Number::bitwiseNOT(oldValue)。
  4. 否则,
    1. 断言oldValue 是 BigInt
    2. 返回 BigInt::bitwiseNOT(oldValue)。

13.5.7 逻辑非运算符(!

13.5.7.1 运行时语义:Evaluation

UnaryExpression : ! UnaryExpression
  1. expr 为 ? UnaryExpressionEvaluation
  2. oldValueToBoolean(? GetValue(expr))。
  3. 如果 oldValuetrue,返回 false
  4. 返回 true

13.6 幂运算符

语法

ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await]

13.6.1 运行时语义:Evaluation

ExponentiationExpression : UpdateExpression ** ExponentiationExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(UpdateExpression, **, ExponentiationExpression)。

13.7 乘法运算符

语法

MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / %
  • * 运算符执行乘法,产生其操作数的乘积。
  • / 运算符执行除法,产生其操作数的商。
  • % 运算符产生隐含除法中其操作数的余数。

13.7.1 运行时语义:Evaluation

MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
  1. opTextMultiplicativeOperator 匹配的源文本
  2. 返回 ? EvaluateStringOrNumericBinaryExpression(MultiplicativeExpression, opText, ExponentiationExpression)。

13.8 加法运算符

语法

AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await]

13.8.1 加法运算符(+

加法运算符执行字符串连接或数值加法。

13.8.1.1 运行时语义:Evaluation

AdditiveExpression : AdditiveExpression + MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, +, MultiplicativeExpression)。

13.8.2 减法运算符(-

- 运算符执行减法,产生其操作数的差。

13.8.2.1 运行时语义:Evaluation

AdditiveExpression : AdditiveExpression - MultiplicativeExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(AdditiveExpression, -, MultiplicativeExpression)。

13.9 按位移位运算符

语法

ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await]

13.9.1 左移运算符(<<

对左操作数执行按位左移操作,移位量由右操作数指定。

13.9.1.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression << AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, <<, AdditiveExpression)。

13.9.2 有符号右移运算符(>>

对左操作数执行符号填充的按位右移操作,移位量由右操作数指定。

13.9.2.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression >> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>, AdditiveExpression)。

13.9.3 无符号右移运算符(>>>

对左操作数执行零填充的按位右移操作,移位量由右操作数指定。

13.9.3.1 运行时语义:Evaluation

ShiftExpression : ShiftExpression >>> AdditiveExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(ShiftExpression, >>>, AdditiveExpression)。

13.10 关系运算符

注 1

关系运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。

语法

RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] 注 2

需要 [In] 语法参数来避免关系表达式中的 in 运算符与 for 语句中的 in 运算符混淆。

13.10.1 运行时语义:Evaluation

RelationalExpression : RelationalExpression < ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 rundefined,返回 false。否则,返回 r
RelationalExpression : RelationalExpression > ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 rundefined,返回 false。否则,返回 r
RelationalExpression : RelationalExpression <= ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(rVal, lVal, false)。
  6. 如果 rtrueundefined,返回 false。否则,返回 true
RelationalExpression : RelationalExpression >= ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLessThan(lVal, rVal, true)。
  6. 如果 rtrueundefined,返回 false。否则,返回 true
RelationalExpression : RelationalExpression instanceof ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? InstanceofOperator(lVal, rVal)。
RelationalExpression : RelationalExpression in ShiftExpression
  1. lRef 为 ? RelationalExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? ShiftExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 如果 rVal 不是对象,抛出 TypeError 异常。
  6. 返回 ? HasProperty(rVal, ? ToPropertyKey(lVal))。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. privateIdentifierPrivateIdentifierStringValue
  2. rRef 为 ? ShiftExpressionEvaluation
  3. rVal 为 ? GetValue(rRef)。
  4. 如果 rVal 不是对象,抛出 TypeError 异常。
  5. privateEnv正在运行的执行上下文的 PrivateEnvironment。
  6. 断言privateEnv 不是 null
  7. privateNameResolvePrivateIdentifier(privateEnv, privateIdentifier)。
  8. 如果 PrivateElementFind(rVal, privateName) 不是 empty,返回 true
  9. 返回 false

13.10.2 InstanceofOperator ( V, target )

抽象操作 InstanceofOperator 接受参数 VECMAScript 语言值)和 targetECMAScript 语言值)并且返回包含布尔值的正常完成抛出完成。它实现用于确定 V 是否为 target 实例的通用算法,通过咨询 target%Symbol.hasInstance% 方法,或如果不存在,则确定 target"prototype" 属性的值是否存在于 V 的原型链中。调用时执行以下步骤:

  1. 如果 target 不是对象,抛出 TypeError 异常。
  2. instOfHandler 为 ? GetMethod(target, %Symbol.hasInstance%)。
  3. 如果 instOfHandler 不是 undefined,则
    1. 返回 ToBoolean(? Call(instOfHandler, target, « V »))。
  4. 如果 IsCallable(target) 是 false,抛出 TypeError 异常。
  5. 返回 ? OrdinaryHasInstance(target, V)。

步骤 45 提供与 ECMAScript 早期版本的兼容性,这些版本没有使用 %Symbol.hasInstance% 方法来定义 instanceof 运算符语义。如果对象没有定义或继承 %Symbol.hasInstance%,它使用默认的 instanceof 语义。

13.11 相等运算符

相等运算符的求值结果总是布尔类型,反映运算符所命名的关系是否在其两个操作数之间成立。

语法

EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await]

13.11.1 运行时语义:Evaluation

EqualityExpression : EqualityExpression == RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? IsLooselyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression != RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. r 为 ? IsLooselyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false。否则,返回 true
EqualityExpression : EqualityExpression === RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 IsStrictlyEqual(rVal, lVal)。
EqualityExpression : EqualityExpression !== RelationalExpression
  1. lRef 为 ? EqualityExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? RelationalExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. rIsStrictlyEqual(rVal, lVal)。
  6. 如果 rtrue,返回 false。否则,返回 true
注 1

根据上述相等性定义:

  • 字符串比较可以通过以下方式强制进行:`${a}` == `${b}`
  • 数值比较可以通过以下方式强制进行:+a == +b
  • 布尔比较可以通过以下方式强制进行:!a == !b
注 2

相等运算符维持以下不变性:

  • A != B 等价于 !(A == B)
  • A == B 等价于 B == A,除了 AB 的求值顺序。
注 3

相等运算符并不总是传递的。例如,可能有两个不同的 String 对象,每个代表相同的 String 值;每个 String 对象都会被 == 运算符认为等于 String 值,但两个 String 对象彼此不相等。例如:

  • new String("a") == "a""a" == new String("a") 都是 true
  • new String("a") == new String("a")false
注 4

字符串的比较使用简单的代码单元值序列相等性测试。没有尝试使用 Unicode 规范中定义的更复杂的、面向语义的字符或字符串相等性和排序定义。因此,根据 Unicode 标准规范相等的字符串值可能测试为不相等。实际上,此算法假设两个字符串都已经是规范化形式。

13.12 二元按位运算符

语法

BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await]

13.12.1 运行时语义:Evaluation

BitwiseANDExpression : BitwiseANDExpression & EqualityExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseANDExpression, &, EqualityExpression)。
BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseXORExpression, ^, BitwiseANDExpression)。
BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression
  1. 返回 ? EvaluateStringOrNumericBinaryExpression(BitwiseORExpression, |, BitwiseXORExpression)。

13.13 二元逻辑运算符

语法

LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await]

&&|| 运算符产生的值不一定是布尔类型。产生的值总是两个操作数表达式之一的值。

13.13.1 运行时语义:Evaluation

LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. lRef 为 ? LogicalANDExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 false,返回 lVal
  4. rRef 为 ? BitwiseORExpressionEvaluation
  5. 返回 ? GetValue(rRef)。
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. lRef 为 ? LogicalORExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 true,返回 lVal
  4. rRef 为 ? LogicalANDExpressionEvaluation
  5. 返回 ? GetValue(rRef)。
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. lRef 为 ? CoalesceExpressionHeadEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lValundefinednull,则
    1. rRef 为 ? BitwiseORExpressionEvaluation
    2. 返回 ? GetValue(rRef)。
  4. 否则,
    1. 返回 lVal

13.14 条件运算符 ( ? : )

语法

ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await]

ECMAScript 中 ConditionalExpression 的语法与 C 和 Java 中的语法略有不同,后者允许第二个子表达式是 Expression,但限制第三个表达式必须是 ConditionalExpression。ECMAScript 中这种差异的动机是允许赋值表达式由条件的任一分支控制,并消除作为中间表达式的逗号表达式这种令人困惑且相当无用的情况。

13.14.1 运行时语义:Evaluation

ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. lRef 为 ? ShortCircuitExpressionEvaluation
  2. lValToBoolean(? GetValue(lRef))。
  3. 如果 lValtrue,则
    1. trueRef 为 ? 第一个 AssignmentExpressionEvaluation
    2. 返回 ? GetValue(trueRef)。
  4. 否则,
    1. falseRef 为 ? 第二个 AssignmentExpressionEvaluation
    2. 返回 ? GetValue(falseRef)。

13.15 赋值运算符

语法

AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

13.15.1 静态语义:早期错误

AssignmentExpression : LeftHandSideExpression = AssignmentExpression AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression

13.15.2 运行时语义:Evaluation

AssignmentExpression : LeftHandSideExpression = AssignmentExpression
  1. 如果 LeftHandSideExpression 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? LeftHandSideExpressionEvaluation
    2. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
      1. lhsLeftHandSideExpressionStringValue
      2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
    3. 否则,
      1. rRef 为 ? AssignmentExpressionEvaluation
      2. rVal 为 ? GetValue(rRef)。
    4. 执行 ? PutValue(lRef, rVal)。
    5. 返回 rVal
  2. assignmentPattern 为由 LeftHandSideExpression 覆盖AssignmentPattern
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 执行 ? assignmentPattern 以参数 rVal 进行的 DestructuringAssignmentEvaluation
  6. 返回 rVal
AssignmentExpression : LeftHandSideExpression AssignmentOperator AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. assignmentOpTextAssignmentOperator 匹配的源代码文本
  6. opText 为下表中与 assignmentOpText 关联的 Unicode 代码点序列:
    assignmentOpText opText
    **= **
    *= *
    /= /
    %= %
    += +
    -= -
    <<= <<
    >>= >>
    >>>= >>>
    &= &
    ^= ^
    |= |
  7. r 为 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。
  8. 执行 ? PutValue(lRef, r)。
  9. 返回 r
AssignmentExpression : LeftHandSideExpression &&= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 false,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ||= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 ToBoolean(lVal) 是 true,返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal
AssignmentExpression : LeftHandSideExpression ??= AssignmentExpression
  1. lRef 为 ? LeftHandSideExpressionEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. 如果 lVal 既不是 undefined 也不是 null, 返回 lVal
  4. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 trueLeftHandSideExpressionIsIdentifierReftrue,则
    1. lhsLeftHandSideExpressionStringValue
    2. rVal 为 ? AssignmentExpression 以参数 lhs 进行的 NamedEvaluation
  5. 否则,
    1. rRef 为 ? AssignmentExpressionEvaluation
    2. rVal 为 ? GetValue(rRef)。
  6. 执行 ? PutValue(lRef, rVal)。
  7. 返回 rVal

当此表达式出现在严格模式代码中时,如果步骤 1.d2222 中的 lRef 是不可解析的引用,这是运行时错误。如果是,则抛出 ReferenceError 异常。此外,如果步骤 8666 中的 lRef 引用具有属性值 { [[Writable]]: false } 的数据属性,或引用具有属性值 { [[Set]]: undefined } 的访问器属性,或引用对象的不存在属性且该对象的 IsExtensible 谓词返回值 false,这是运行时错误。在这些情况下会抛出 TypeError 异常。

13.15.3 ApplyStringOrNumericBinaryOperator ( lVal, opText, rVal )

抽象操作 ApplyStringOrNumericBinaryOperator 接受参数 lVal(一个ECMAScript 语言值)、 opText***/%+-<<>>>>>&^|)和 rVal(一个ECMAScript 语言值),并返回包含 String、BigInt 或 Number 的正常完成,或抛出完成。当调用时,它执行以下步骤:

  1. 如果 opText+,则
    1. lPrim 为 ? ToPrimitive(lVal)。
    2. rPrim 为 ? ToPrimitive(rVal)。
    3. 如果 lPrim 是 StringrPrim 是 String,则
      1. lStr 为 ? ToString(lPrim)。
      2. rStr 为 ? ToString(rPrim)。
      3. 返回 lStrrStr字符串拼接
    4. 设置 lVallPrim
    5. 设置 rValrPrim
  2. 注:此时,这必须是数值运算。
  3. lNum 为 ? ToNumeric(lVal)。
  4. rNum 为 ? ToNumeric(rVal)。
  5. 如果 SameType(lNum, rNum) 是 false,抛出 TypeError 异常。
  6. 如果 lNum 是 BigInt,则
    1. 如果 opText**,返回 ? BigInt::exponentiate(lNum, rNum)。
    2. 如果 opText/,返回 ? BigInt::divide(lNum, rNum)。
    3. 如果 opText%,返回 ? BigInt::remainder(lNum, rNum)。
    4. 如果 opText>>>,返回 ? BigInt::unsignedRightShift(lNum, rNum)。
    5. operation 为下表中与 opText 关联的抽象操作:
      opText operation
      * BigInt::multiply
      + BigInt::add
      - BigInt::subtract
      << BigInt::leftShift
      >> BigInt::signedRightShift
      & BigInt::bitwiseAND
      ^ BigInt::bitwiseXOR
      | BigInt::bitwiseOR
  7. 否则,
    1. 断言lNum 是 Number
    2. operation 为下表中与 opText 关联的抽象操作:
      opText operation
      ** Number::exponentiate
      * Number::multiply
      / Number::divide
      % Number::remainder
      + Number::add
      - Number::subtract
      << Number::leftShift
      >> Number::signedRightShift
      >>> Number::unsignedRightShift
      & Number::bitwiseAND
      ^ Number::bitwiseXOR
      | Number::bitwiseOR
  8. 返回 operation(lNum, rNum)。
注 1

在步骤 1.a1.b 中对 ToPrimitive 的调用中没有提供提示。除 Date 外的所有标准对象都将缺少提示处理为给定 number;Date 将缺少提示处理为给定 string异质对象可能以其他方式处理缺少提示的情况。

注 2

步骤 1.cIsLessThan 算法的步骤 3 不同,使用逻辑或运算而不是逻辑与运算。

13.15.4 EvaluateStringOrNumericBinaryExpression ( leftOperand, opText, rightOperand )

抽象操作 EvaluateStringOrNumericBinaryExpression 接受参数 leftOperand(一个解析节点)、opText(一个 Unicode 代码点序列)和 rightOperand(一个解析节点),并返回包含 String、BigInt 或 Number 的正常完成,或异常完成。当调用时,它执行以下步骤:

  1. lRef 为 ? leftOperandEvaluation
  2. lVal 为 ? GetValue(lRef)。
  3. rRef 为 ? rightOperandEvaluation
  4. rVal 为 ? GetValue(rRef)。
  5. 返回 ? ApplyStringOrNumericBinaryOperator(lVal, opText, rVal)。

13.15.5 解构赋值

补充语法

在处理产生式实例的某些情况下
AssignmentExpression : LeftHandSideExpression = AssignmentExpression
使用以下语法来细化对 LeftHandSideExpression 的解释:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

13.15.5.1 静态语义:早期错误

AssignmentProperty : IdentifierReference Initializeropt AssignmentRestProperty : ... DestructuringAssignmentTarget DestructuringAssignmentTarget : LeftHandSideExpression

13.15.5.2 运行时语义:DestructuringAssignmentEvaluation

语法导向操作 DestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

ObjectAssignmentPattern : { }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 返回 unused
ObjectAssignmentPattern : { AssignmentPropertyList } { AssignmentPropertyList , }
  1. 执行 ? RequireObjectCoercible(value)。
  2. 执行 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 unused
ObjectAssignmentPattern : { AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为一个新的空列表
  3. 返回 ? AssignmentRestProperty 以参数 valueexcludedNames 进行的 RestDestructuringAssignmentEvaluation
ObjectAssignmentPattern : { AssignmentPropertyList , AssignmentRestProperty }
  1. 执行 ? RequireObjectCoercible(value)。
  2. excludedNames 为 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 ? AssignmentRestProperty 以参数 valueexcludedNames 进行的 RestDestructuringAssignmentEvaluation
ArrayAssignmentPattern : [ ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 返回 ? IteratorClose(iteratorRecord, NormalCompletion(unused))。
ArrayAssignmentPattern : [ Elision ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ Elisionopt AssignmentRestElement ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. 如果存在 Elision,则
    1. statusCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
    2. 如果 status异常完成,则
      1. 断言iteratorRecord.[[Done]]true
      2. 返回 ? status
  3. resultCompletion(AssignmentRestElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  4. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  5. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. resultCompletion(AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, result)。
  4. 返回 result
ArrayAssignmentPattern : [ AssignmentElementList , Elisionopt AssignmentRestElementopt ]
  1. iteratorRecord 为 ? GetIterator(value, sync)。
  2. statusCompletion(AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  3. 如果 status异常完成,则
    1. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
    2. 返回 ? status
  4. 如果存在 Elision,则
    1. 设置 statusCompletion(Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
    2. 如果 status异常完成,则
      1. 断言iteratorRecord.[[Done]]true
      2. 返回 ? status
  5. 如果存在 AssignmentRestElement,则
    1. 设置 statusCompletion(AssignmentRestElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation)。
  6. 如果 iteratorRecord.[[Done]]false,返回 ? IteratorClose(iteratorRecord, status)。
  7. 返回 ? status

13.15.5.3 运行时语义:PropertyDestructuringAssignmentEvaluation

语法导向操作 PropertyDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值),并返回包含属性键列表正常完成异常完成。它收集所有解构的属性键的列表。它在以下产生式上分段定义:

AssignmentPropertyList : AssignmentPropertyList , AssignmentProperty
  1. propertyNames 为 ? AssignmentPropertyList 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  2. nextNames 为 ? AssignmentProperty 以参数 value 进行的 PropertyDestructuringAssignmentEvaluation
  3. 返回 propertyNamesnextNames列表拼接
AssignmentProperty : IdentifierReference Initializeropt
  1. PIdentifierReferenceStringValue
  2. lRef 为 ? ResolveBinding(P)。
  3. v 为 ? GetV(value, P)。
  4. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? Initializer 以参数 P 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. 设置 v 为 ? GetValue(defaultValue)。
  5. 执行 ? PutValue(lRef, v)。
  6. 返回 « P »。
AssignmentProperty : PropertyName : AssignmentElement
  1. name 为 ? PropertyNameEvaluation
  2. 执行 ? AssignmentElement 以参数 valuename 进行的 KeyedDestructuringAssignmentEvaluation
  3. 返回 « name »。

13.15.5.4 运行时语义:RestDestructuringAssignmentEvaluation

语法导向操作 RestDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值)和 excludedNames属性键列表),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentRestProperty : ... DestructuringAssignmentTarget
  1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObj, value, excludedNames)。
  4. 返回 ? PutValue(lRef, restObj)。

13.15.5.5 运行时语义:IteratorDestructuringAssignmentEvaluation

语法导向操作 IteratorDestructuringAssignmentEvaluation 接受参数 iteratorRecord(一个迭代器记录),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentElementList : AssignmentElisionElement
  1. 返回 ? AssignmentElisionElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElementList : AssignmentElementList , AssignmentElisionElement
  1. 执行 ? AssignmentElementList 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? AssignmentElisionElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : AssignmentElement
  1. 返回 ? AssignmentElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
AssignmentElisionElement : Elision AssignmentElement
  1. 执行 ? Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 返回 ? AssignmentElement 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
Elision : ,
  1. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  2. 返回 unused
Elision : Elision ,
  1. 执行 ? Elision 以参数 iteratorRecord 进行的 IteratorDestructuringAssignmentEvaluation
  2. 如果 iteratorRecord.[[Done]]false,则
    1. 执行 ? IteratorStep(iteratorRecord)。
  3. 返回 unused
AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. valueundefined
  3. 如果 iteratorRecord.[[Done]]false,则
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 设置 valuenext
  4. 如果存在 Initializervalueundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. v 为 ? Initializer 以参数 target 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. v 为 ? GetValue(defaultValue)。
  5. 否则,
    1. vvalue
  6. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? nestedAssignmentPattern 以参数 v 进行的 DestructuringAssignmentEvaluation
  7. 返回 ? PutValue(lRef, v)。

通过在访问迭代器或计算 Initializer 之前先计算不是解构模式的 DestructuringAssignmentTarget,来维持从左到右的求值顺序。

AssignmentRestElement : ... DestructuringAssignmentTarget
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. A 为 ! ArrayCreate(0)。
  3. n 为 0。
  4. 重复,只要 iteratorRecord.[[Done]]false
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 next 不是 done,则
      1. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), next)。
      2. 设置 nn + 1。
  5. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. 返回 ? PutValue(lRef, A)。
  6. nestedAssignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
  7. 返回 ? nestedAssignmentPattern 以参数 A 进行的 DestructuringAssignmentEvaluation

13.15.5.6 运行时语义:KeyedDestructuringAssignmentEvaluation

语法导向操作 KeyedDestructuringAssignmentEvaluation 接受参数 value(一个ECMAScript 语言值)和 propertyName(一个属性键),并返回包含 unused正常完成异常完成。 它在以下产生式上分段定义:

AssignmentElement : DestructuringAssignmentTarget Initializeropt
  1. 如果 DestructuringAssignmentTarget 既不是 ObjectLiteral 也不是 ArrayLiteral,则
    1. lRef 为 ? DestructuringAssignmentTargetEvaluation
  2. v 为 ? GetV(value, propertyName)。
  3. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 trueDestructuringAssignmentTargetIsIdentifierReftrue,则
      1. targetDestructuringAssignmentTargetStringValue
      2. rhsValue 为 ? Initializer 以参数 target 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. rhsValue 为 ? GetValue(defaultValue)。
  4. 否则,
    1. rhsValuev
  5. 如果 DestructuringAssignmentTargetObjectLiteralArrayLiteral,则
    1. assignmentPattern 为被 DestructuringAssignmentTarget 覆盖AssignmentPattern
    2. 返回 ? assignmentPattern 以参数 rhsValue 进行的 DestructuringAssignmentEvaluation
  6. 返回 ? PutValue(lRef, rhsValue)。

13.16 逗号操作符 ( , )

语法

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

13.16.1 运行时语义:Evaluation

Expression : Expression , AssignmentExpression
  1. lRef 为 ? ExpressionEvaluation
  2. 执行 ? GetValue(lRef)。
  3. rRef 为 ? AssignmentExpressionEvaluation
  4. 返回 ? GetValue(rRef)。

必须调用 GetValue,即使其值未被使用,因为它可能具有可观察的副作用。

14 ECMAScript 语言:语句和声明

语法

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return]

14.1 语句语义

14.1.1 运行时语义:Evaluation

HoistableDeclaration : GeneratorDeclaration AsyncFunctionDeclaration AsyncGeneratorDeclaration
  1. 返回 empty
HoistableDeclaration : FunctionDeclaration
  1. 返回 ? FunctionDeclarationEvaluation
BreakableStatement : IterationStatement SwitchStatement
  1. newLabelSet 为一个新的空列表
  2. 返回 ? 此 BreakableStatement 以参数 newLabelSet 进行的 LabelledEvaluation

14.2

语法

BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await]

14.2.1 静态语义:早期错误

Block : { StatementList }

14.2.2 运行时语义:Evaluation

Block : { }
  1. 返回 empty
Block : { StatementList }
  1. oldEnv运行中执行上下文的 LexicalEnvironment。
  2. blockEnvNewDeclarativeEnvironment(oldEnv)。
  3. 执行 BlockDeclarationInstantiation(StatementList, blockEnv)。
  4. 设置运行中执行上下文的 LexicalEnvironment 为 blockEnv
  5. blockValueCompletion(StatementListEvaluation)。
  6. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
  7. 返回 ? blockValue
注1

无论控制如何离开 Block,LexicalEnvironment 总是恢复到其之前的状态。

StatementList : StatementList StatementListItem
  1. sl 为 ? StatementListEvaluation
  2. sCompletion(StatementListItemEvaluation)。
  3. 返回 ? UpdateEmpty(s, sl)。
注2

StatementList 的值是 StatementList 中最后一个产生值的项的值。例如,以下对 eval 函数的调用都返回值 1:

eval("1;;;;;")
eval("1;{}")
eval("1;var a;")

14.2.3 BlockDeclarationInstantiation ( code, env )

抽象操作 BlockDeclarationInstantiation 接受参数 code(一个解析节点)和 env(一个声明式环境记录),并返回 unusedcode 是对应于块主体的解析节点env 是要在其中创建绑定的环境记录

当计算 BlockCaseBlock 时,会创建一个新的声明式环境记录,并且块中声明的每个块作用域变量、常量、函数或类的绑定会在环境记录中实例化。

调用时执行以下步骤:

  1. declarationscodeLexicallyScopedDeclarations
  2. privateEnv运行中执行上下文的 PrivateEnvironment。
  3. 对于 declarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,则
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! env.CreateMutableBinding(dn, false)。注:此步骤在 B.3.2.6 节中被替换。
    2. 如果 dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,则
      1. fndBoundNames 的唯一元素。
      2. fod 以参数 envprivateEnv 进行的 InstantiateFunctionObject
      3. 执行 ! env.InitializeBinding(fn, fo)。 注:此步骤在 B.3.2.6 节中被替换。
  4. 返回 unused

14.3 声明和变量语句

14.3.1 Let 和 Const 声明

letconst 声明定义的变量作用域限定在运行中执行上下文的 LexicalEnvironment。这些变量在其包含的环境记录实例化时创建,但在变量的 LexicalBinding 被计算之前不能以任何方式访问。由带有 InitializerLexicalBinding 定义的变量在 LexicalBinding 被计算时(而不是在变量创建时)被赋予其 InitializerAssignmentExpression 的值。如果 let 声明中的 LexicalBinding 没有 Initializer,则在 LexicalBinding 被计算时,该变量被赋值为 undefined

语法

LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.1.1 静态语义:早期错误

LexicalDeclaration : LetOrConst BindingList ; LexicalBinding : BindingIdentifier Initializeropt

14.3.1.2 运行时语义:Evaluation

LexicalDeclaration : LetOrConst BindingList ;
  1. 执行 ? BindingListEvaluation
  2. 返回 empty
BindingList : BindingList , LexicalBinding
  1. 执行 ? BindingListEvaluation
  2. 返回 ? LexicalBindingEvaluation
LexicalBinding : BindingIdentifier
  1. lhs 为 ! ResolveBinding(BindingIdentifierStringValue)。
  2. 执行 ! InitializeReferencedBinding(lhs, undefined)。
  3. 返回 empty

静态语义规则确保这种形式的 LexicalBinding 永远不会出现在 const 声明中。

LexicalBinding : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ! ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
  4. 否则,
    1. rhs 为 ? InitializerEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 执行 ! InitializeReferencedBinding(lhs, value)。
  6. 返回 empty
LexicalBinding : BindingPattern Initializer
  1. rhs 为 ? InitializerEvaluation
  2. value 为 ? GetValue(rhs)。
  3. env运行中执行上下文的 LexicalEnvironment。
  4. 返回 ? BindingPattern 以参数 valueenv 进行的 BindingInitialization

14.3.2 变量语句

var 语句声明的变量作用域限定在运行中执行上下文的 VariableEnvironment。var 变量在其包含的环境记录实例化时创建,并在创建时初始化为 undefined。在任何 VariableEnvironment 的作用域内,相同的 BindingIdentifier 可以出现在多个 VariableDeclaration 中,但这些声明共同只定义一个变量。由带有 InitializerVariableDeclaration 定义的变量在 VariableDeclaration 执行时(而不是在变量创建时)被赋予其 InitializerAssignmentExpression 的值。

语法

VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]

14.3.2.1 运行时语义:Evaluation

VariableStatement : var VariableDeclarationList ;
  1. 执行 ? VariableDeclarationListEvaluation
  2. 返回 empty
VariableDeclarationList : VariableDeclarationList , VariableDeclaration
  1. 执行 ? VariableDeclarationListEvaluation
  2. 返回 ? VariableDeclarationEvaluation
VariableDeclaration : BindingIdentifier
  1. 返回 empty
VariableDeclaration : BindingIdentifier Initializer
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingId)。
  3. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
    1. value 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
  4. 否则,
    1. rhs 为 ? InitializerEvaluation
    2. value 为 ? GetValue(rhs)。
  5. 执行 ? PutValue(lhs, value)。
  6. 返回 empty

如果 VariableDeclaration 嵌套在 with 语句中,且 VariableDeclaration 中的 BindingIdentifier 与 with 语句的对象环境记录的绑定对象的属性名相同,则步骤 5 将把 value 赋值给该属性,而不是赋值给 Identifier 的 VariableEnvironment 绑定。

VariableDeclaration : BindingPattern Initializer
  1. rhs 为 ? InitializerEvaluation
  2. rVal 为 ? GetValue(rhs)。
  3. 返回 ? BindingPattern 以参数 rValundefined 进行的 BindingInitialization

14.3.3 解构绑定模式

语法

BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await]

14.3.3.1 运行时语义:PropertyBindingInitialization

语法制导操作 PropertyBindingInitialization 接受参数 value(一个ECMAScript 语言值)和 environment(一个环境记录undefined),并返回包含列表属性键的正常完成或突然完成。它收集所有已绑定属性名的列表。它在以下产生式上分段定义:

BindingPropertyList : BindingPropertyList , BindingProperty
  1. boundNames 为 ? BindingPropertyList 以参数 valueenvironment 进行的 PropertyBindingInitialization
  2. nextNames 为 ? BindingProperty 以参数 valueenvironment 进行的 PropertyBindingInitialization
  3. 返回 boundNamesnextNames列表连接
BindingProperty : SingleNameBinding
  1. nameSingleNameBindingBoundNames 的唯一元素。
  2. 执行 ? SingleNameBinding 以参数 valueenvironmentname 进行的 KeyedBindingInitialization
  3. 返回 « name »。
BindingProperty : PropertyName : BindingElement
  1. P 为 ? PropertyNameEvaluation
  2. 执行 ? BindingElement 以参数 valueenvironmentP 进行的 KeyedBindingInitialization
  3. 返回 « P »。

14.3.3.2 运行时语义:RestBindingInitialization

语法制导操作 RestBindingInitialization 接受参数 value (一个ECMAScript 语言值)、 environment(一个环境记录undefined)和 excludedNames(一个列表,包含属性键),并返回包含 unused 的正常完成或突然完成。它在以下产生式上分段定义:

BindingRestProperty : ... BindingIdentifier
  1. lhs 为 ? ResolveBinding(BindingIdentifierStringValueenvironment)。
  2. restObjOrdinaryObjectCreate(%Object.prototype%)。
  3. 执行 ? CopyDataProperties(restObjvalueexcludedNames)。
  4. 如果 environmentundefined,返回 ? PutValue(lhsrestObj)。
  5. 返回 ? InitializeReferencedBinding(lhsrestObj)。

14.3.3.3 运行时语义:KeyedBindingInitialization

语法制导操作 KeyedBindingInitialization 接受参数 value (一个ECMAScript 语言值)、 environment(一个环境记录undefined)和 propertyName(一个属性键),并返回包含 unused 的正常完成或突然完成

当为 environment 传递 undefined 时,表示应该使用 PutValue 操作来分配初始化值。这是非严格函数的形参列表的情况。在这种情况下,形参绑定会被预初始化,以处理可能存在多个同名参数的情况。

它在以下产生式上分段定义:

BindingElement : BindingPattern Initializeropt
  1. v 为 ? GetV(valuepropertyName)。
  2. 如果存在 Initializervundefined,则
    1. defaultValue 为 ? InitializerEvaluation
    2. 设置 v 为 ? GetValue(defaultValue)。
  3. 返回 ? BindingPattern 以参数 venvironment 进行的 BindingInitialization
SingleNameBinding : BindingIdentifier Initializeropt
  1. bindingIdBindingIdentifierStringValue
  2. lhs 为 ? ResolveBinding(bindingIdenvironment)。
  3. v 为 ? GetV(valuepropertyName)。
  4. 如果存在 Initializervundefined,则
    1. 如果 IsAnonymousFunctionDefinition(Initializer) 是 true,则
      1. 设置 v 为 ? Initializer 以参数 bindingId 进行的 NamedEvaluation
    2. 否则,
      1. defaultValue 为 ? InitializerEvaluation
      2. 设置 v 为 ? GetValue(defaultValue)。
  5. 如果 environmentundefined,返回 ? PutValue(lhsv)。
  6. 返回 ? InitializeReferencedBinding(lhsv)。

14.4 空语句

语法

EmptyStatement : ;

14.4.1 运行时语义:Evaluation

EmptyStatement : ;
  1. 返回 empty

14.5 表达式语句

语法

ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ;

ExpressionStatement 不能以 U+007B(左花括号)开头,因为这可能会与 Block 产生歧义。ExpressionStatement 不能以 functionclass 关键字开头,因为这会与 FunctionDeclarationGeneratorDeclarationClassDeclaration 产生歧义。 ExpressionStatement 不能以 async function 开头,因为这会与 AsyncFunctionDeclarationAsyncGeneratorDeclaration 产生歧义。ExpressionStatement 不能以两个词法单元序列 let [ 开头,因为这会与 let LexicalDeclaration 产生歧义,其第一个 LexicalBindingArrayBindingPattern

14.5.1 运行时语义:Evaluation

ExpressionStatement : Expression ;
  1. exprRef 为 ? ExpressionEvaluation
  2. 返回 ? GetValue(exprRef)。

14.6 if 语句

语法

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else]
前瞻限制 [lookahead ≠ else] 以通常的方式解决了经典的"悬空 else"问题。也就是说,当关联的 if 的选择在其他方面模糊时,else 与候选 if 中最近的(最内层的)关联。

14.6.1 静态语义:早期错误

IfStatement : if ( Expression ) Statement else Statement IfStatement : if ( Expression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.6.2 运行时语义:Evaluation

IfStatement : if ( Expression ) Statement else Statement
  1. exprRef 为 ? ExpressionEvaluation
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuetrue,则
    1. stmtCompletionCompletion(第一个 StatementEvaluation)。
  4. 否则,
    1. stmtCompletionCompletion(第二个 StatementEvaluation)。
  5. 返回 ? UpdateEmpty(stmtCompletionundefined)。
IfStatement : if ( Expression ) Statement
  1. exprRef 为 ? ExpressionEvaluation
  2. exprValueToBoolean(? GetValue(exprRef))。
  3. 如果 exprValuefalse,则
    1. 返回 undefined
  4. 否则,
    1. stmtCompletionCompletion(StatementEvaluation)。
    2. 返回 ? UpdateEmpty(stmtCompletionundefined)。

14.7 迭代语句

语法

IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return]

14.7.1 语义

14.7.1.1 LoopContinues ( completion, labelSet )

抽象操作 LoopContinues 接受参数 completion(一个完成记录) 和 labelSet(一个列表,包含字符串),并返回一个布尔值。调用时执行以下步骤:

  1. 如果 completion正常完成,返回 true
  2. 如果 completion 不是continue 完成,返回 false
  3. 如果 completion.[[Target]]empty,返回 true
  4. 如果 labelSet 包含 completion.[[Target]],返回 true
  5. 返回 false

IterationStatementStatement 部分内,可以使用 ContinueStatement 来开始新的迭代。

14.7.1.2 运行时语义:LoopEvaluation

语法制导操作 LoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

IterationStatement : DoWhileStatement
  1. 返回 ? DoWhileStatement 以参数 labelSet 进行的 DoWhileLoopEvaluation
IterationStatement : WhileStatement
  1. 返回 ? WhileStatement 以参数 labelSet 进行的 WhileLoopEvaluation
IterationStatement : ForStatement
  1. 返回 ? ForStatement 以参数 labelSet 进行的 ForLoopEvaluation
IterationStatement : ForInOfStatement
  1. 返回 ? ForInOfStatement 以参数 labelSet 进行的 ForInOfLoopEvaluation

14.7.2 do-while 语句

语法

DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ;

14.7.2.1 静态语义:早期错误

DoWhileStatement : do Statement while ( Expression ) ;

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.7.2.2 运行时语义:DoWhileLoopEvaluation

语法制导操作 DoWhileLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

DoWhileStatement : do Statement while ( Expression ) ;
  1. Vundefined
  2. 重复,
    1. stmtResultCompletion(StatementEvaluation)。
    2. 如果 LoopContinues(stmtResultlabelSet) 是 false,返回 ? UpdateEmpty(stmtResultV)。
    3. 如果 stmtResult.[[Value]] 不是 empty,设置 VstmtResult.[[Value]]
    4. exprRef 为 ? ExpressionEvaluation
    5. exprValue 为 ? GetValue(exprRef)。
    6. 如果 ToBoolean(exprValue) 是 false,返回 V

14.7.3 while 语句

语法

WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

14.7.3.1 静态语义:早期错误

WhileStatement : while ( Expression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

14.7.3.2 运行时语义:WhileLoopEvaluation

语法制导操作 WhileLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

WhileStatement : while ( Expression ) Statement
  1. Vundefined
  2. 重复,
    1. exprRef 为 ? ExpressionEvaluation
    2. exprValue 为 ? GetValue(exprRef)。
    3. 如果 ToBoolean(exprValue) 是 false,返回 V
    4. stmtResultCompletion(StatementEvaluation)。
    5. 如果 LoopContinues(stmtResultlabelSet) 是 false,返回 ? UpdateEmpty(stmtResultV)。
    6. 如果 stmtResult.[[Value]] 不是 empty,设置 VstmtResult.[[Value]]

14.7.4 for 语句

语法

ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return]

14.7.4.1 静态语义:早期错误

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

14.7.4.2 运行时语义:ForLoopEvaluation

语法制导操作 ForLoopEvaluation 接受参数 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement
  1. 如果第一个 Expression 存在,则
    1. exprRef 为 ? 第一个 ExpressionEvaluation
    2. 执行 ? GetValue(exprRef)。
  2. 如果第二个 Expression 存在,令 test 为第二个 Expression;否则,令 testempty
  3. 如果第三个 Expression 存在,令 increment 为第三个 Expression;否则,令 incrementempty
  4. 返回 ? ForBodyEvaluation(testincrementStatement,« », labelSet)。
ForStatement : for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement
  1. 执行 ? VariableDeclarationListEvaluation
  2. 如果第一个 Expression 存在,令 test 为第一个 Expression;否则,令 testempty
  3. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则,令 incrementempty
  4. 返回 ? ForBodyEvaluation(testincrementStatement,« », labelSet)。
ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement
  1. oldEnv运行中执行上下文的 LexicalEnvironment。
  2. loopEnvNewDeclarativeEnvironment(oldEnv)。
  3. isConstLexicalDeclarationIsConstantDeclaration
  4. boundNamesLexicalDeclarationBoundNames
  5. boundNames 的每个元素 dn,执行
    1. 如果 isConsttrue,则
      1. 执行 ! loopEnv.CreateImmutableBinding(dntrue)。
    2. 否则,
      1. 执行 ! loopEnv.CreateMutableBinding(dnfalse)。
  6. 设置运行中执行上下文的 LexicalEnvironment 为 loopEnv
  7. forDclCompletion(LexicalDeclarationEvaluation)。
  8. 如果 forDcl突然完成,则
    1. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
    2. 返回 ? forDcl
  9. 如果 isConstfalse,令 perIterationLetsboundNames;否则令 perIterationLets 为新的空列表
  10. 如果第一个 Expression 存在,令 test 为第一个 Expression;否则,令 testempty
  11. 如果第二个 Expression 存在,令 increment 为第二个 Expression;否则,令 incrementempty
  12. bodyResultCompletion(ForBodyEvaluation(testincrementStatementperIterationLetslabelSet))。
  13. 设置运行中执行上下文的 LexicalEnvironment 为 oldEnv
  14. 返回 ? bodyResult

14.7.4.3 ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )

抽象操作 ForBodyEvaluation 接受参数 test(一个 Expression 解析节点empty)、increment(一个 Expression 解析节点empty)、stmt(一个 Statement 解析节点)、perIterationBindings(一个列表,包含字符串)和 labelSet(一个列表,包含字符串),并返回包含ECMAScript 语言值的正常完成或突然完成。调用时执行以下步骤:

  1. Vundefined
  2. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
  3. 重复,
    1. 如果 test 不是 empty,则
      1. testRef 为 ? testEvaluation
      2. testValue 为 ? GetValue(testRef)。
      3. 如果 ToBoolean(testValue) 是 false,返回 V
    2. resultCompletion(stmtEvaluation)。
    3. 如果 LoopContinues(resultlabelSet) 是 false,返回 ? UpdateEmpty(resultV)。
    4. 如果 result.[[Value]] 不是 empty,设置 Vresult.[[Value]]
    5. 执行 ? CreatePerIterationEnvironment(perIterationBindings)。
    6. 如果 increment 不是 empty,则
      1. incRef 为 ? incrementEvaluation
      2. 执行 ? GetValue(incRef)。

14.7.4.4 CreatePerIterationEnvironment ( perIterationBindings )

抽象操作 CreatePerIterationEnvironment 接受参数 perIterationBindings(一个列表,包含字符串),并返回包含 unused 的正常完成或throw 完成。调用时执行以下步骤:

  1. 如果 perIterationBindings 有任何元素,则
    1. lastIterationEnv运行中执行上下文的 LexicalEnvironment。
    2. outerlastIterationEnv.[[OuterEnv]]
    3. 断言outer 不是 null
    4. thisIterationEnvNewDeclarativeEnvironment(outer)。
    5. perIterationBindings 的每个元素 bn,执行
      1. 执行 ! thisIterationEnv.CreateMutableBinding(bnfalse)。
      2. lastValue 为 ? lastIterationEnv.GetBindingValue(bntrue)。
      3. 执行 ! thisIterationEnv.InitializeBinding(bnlastValue)。
    6. 设置运行中执行上下文的 LexicalEnvironment 为 thisIterationEnv
  2. 返回 unused

14.7.5 for-infor-offor-await-of 语句

语法

ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await]

本节由附录B.3.5 扩展。

14.7.5.1 静态语义:早期错误

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( var ForBinding of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

只有在实现B.3.1 中指定的扩展时,才需要应用此规则。

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( LeftHandSideExpression of AssignmentExpression ) Statement for await ( LeftHandSideExpression of AssignmentExpression ) Statement ForInOfStatement : for ( ForDeclaration in Expression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement for await ( ForDeclaration of AssignmentExpression ) Statement

14.7.5.2 静态语义:IsDestructuring

语法制导操作 IsDestructuring 不接受参数并返回布尔值。它在以下产生式上分段定义:

MemberExpression : PrimaryExpression
  1. 如果 PrimaryExpressionObjectLiteralArrayLiteral, 返回 true
  2. 返回 false
MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName MemberExpression TemplateLiteral SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier NewExpression : new NewExpression LeftHandSideExpression : CallExpression OptionalExpression
  1. 返回 false
ForDeclaration : LetOrConst ForBinding
  1. 返回 ForBindingIsDestructuring
ForBinding : BindingIdentifier
  1. 返回 false
ForBinding : BindingPattern
  1. 返回 true

本节由附录B.3.5 扩展。

14.7.5.3 运行时语义:ForDeclarationBindingInitialization

语法制导操作 ForDeclarationBindingInitialization 接受参数 value(一个ECMAScript 语言值)和 environment(一个环境记录undefined),并返回包含 unused 的正常完成或突然完成

传递 undefined 作为 environment 表示应该使用 PutValue 操作来分配初始化值。这是 var 语句和某些非严格函数的形式参数列表的情况(见10.2.11)。在这些情况下,词法绑定被提升并在其初始化程序求值之前预初始化。

它在以下产生式上分段定义:

ForDeclaration : LetOrConst ForBinding
  1. 返回 ? ForBinding 以参数 valueenvironment 进行的 BindingInitialization

14.7.5.4 运行时语义:ForDeclarationBindingInstantiation

语法制导操作 ForDeclarationBindingInstantiation 接受参数 environment(一个声明式环境记录)并返回 unused。它在以下产生式上分段定义:

ForDeclaration : LetOrConst ForBinding
  1. ForBindingBoundNames 的每个元素 name,执行
    1. 如果 LetOrConstIsConstantDeclarationtrue,则
      1. 执行 ! environment.CreateImmutableBinding(nametrue)。
    2. 否则,
      1. 执行 ! environment.CreateMutableBinding(namefalse)。
  2. 返回 unused

14.7.5.5 运行时语义:ForInOfLoopEvaluation

语法制导操作 ForInOfLoopEvaluation 接受参数 labelSet(一个包含字符串的列表),并返回包含ECMAScript 语言值的正常完成或突然完成。它在以下产生式上分段定义:

ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, enumerate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, enumerate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration in Expression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclarationBoundNames, Expression, enumerate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, enumerate, lexical-binding, labelSet)。
ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet)。
ForInOfStatement : for ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet)。
ForInOfStatement : for ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclarationBoundNames, AssignmentExpression, iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet)。
ForInOfStatement : for await ( LeftHandSideExpression of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(LeftHandSideExpression, Statement, keyResult, iterate, assignment, labelSet, async)。
ForInOfStatement : for await ( var ForBinding of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(« », AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForBinding, Statement, keyResult, iterate, var-binding, labelSet, async)。
ForInOfStatement : for await ( ForDeclaration of AssignmentExpression ) Statement
  1. keyResult 为 ? ForIn/OfHeadEvaluation(ForDeclarationBoundNames, AssignmentExpression, async-iterate)。
  2. 返回 ? ForIn/OfBodyEvaluation(ForDeclaration, Statement, keyResult, iterate, lexical-binding, labelSet, async)。

本节由附录B.3.5 扩展。

14.7.5.6 ForIn/OfHeadEvaluation ( uninitializedBoundNames, expr, iterationKind )

抽象操作 ForIn/OfHeadEvaluation 接受参数 uninitializedBoundNames(一个包含字符串的列表)、 expr(一个 Expression 解析节点或一个 AssignmentExpression 解析节点),以及 iterationKindenumerateiterateasync-iterate),并返回包含迭代器记录的正常完成或突然完成。它在被调用时执行以下步骤:

  1. oldEnv运行执行上下文的 LexicalEnvironment。
  2. 如果 uninitializedBoundNames 不为空,则
    1. 断言uninitializedBoundNames 没有重复的条目。
    2. newEnvNewDeclarativeEnvironment(oldEnv)。
    3. uninitializedBoundNames 的每个字符串 name,执行
      1. 执行 ! newEnv.CreateMutableBinding(name, false)。
    4. 设置运行执行上下文的 LexicalEnvironment 为 newEnv
  3. exprRefCompletion(Evaluation of expr)。
  4. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
  5. exprValue 为 ? GetValue(? exprRef)。
  6. 如果 iterationKindenumerate,则
    1. 如果 exprValueundefinednull,则
      1. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
    2. obj 为 ! ToObject(exprValue)。
    3. iteratorEnumerateObjectProperties(obj)。
    4. nextMethod 为 ! GetV(iterator, "next")。
    5. 返回迭代器记录 { [[Iterator]]: iterator, [[NextMethod]]: nextMethod, [[Done]]: false }。
  7. 否则,
    1. 断言iterationKinditerateasync-iterate
    2. 如果 iterationKindasync-iterate,令 iteratorKindasync
    3. 否则,令 iteratorKindsync
    4. 返回 ? GetIterator(exprValue, iteratorKind)。

14.7.5.7 ForIn/OfBodyEvaluation ( lhs, stmt, iteratorRecord, iterationKind, lhsKind, labelSet [ , iteratorKind ] )

抽象操作 ForIn/OfBodyEvaluation 接受参数 lhs(一个解析节点)、stmt(一个 Statement 解析节点)、iteratorRecord(一个迭代器记录)、iterationKindenumerateiterate)、lhsKindassignmentvar-bindinglexical-binding)、labelSet(一个包含字符串的列表)以及可选参数 iteratorKindsyncasync),并返回包含ECMAScript 语言值的正常完成或突然完成。它在被调用时执行以下步骤:

  1. 如果 iteratorKind 不存在,设置 iteratorKindsync
  2. oldEnv运行执行上下文的 LexicalEnvironment。
  3. Vundefined
  4. destructuringlhsIsDestructuring
  5. 如果 destructuringtruelhsKindassignment,则
    1. 断言lhs 是一个 LeftHandSideExpression
    2. assignmentPattern 为被 lhs 覆盖AssignmentPattern
  6. 重复,
    1. nextResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]])。
    2. 如果 iteratorKindasync,设置 nextResult 为 ? Await(nextResult)。
    3. 如果 nextResult 不是对象,抛出 TypeError 异常。
    4. done 为 ? IteratorComplete(nextResult)。
    5. 如果 donetrue,返回 V
    6. nextValue 为 ? IteratorValue(nextResult)。
    7. 如果 lhsKindassignmentvar-binding,则
      1. 如果 destructuringtrue,则
        1. 如果 lhsKindassignment, 则
          1. statusCompletion(以参数 nextValueassignmentPattern 进行的 DestructuringAssignmentEvaluation)。
        2. 否则,
          1. 断言lhsKindvar-binding
          2. 断言lhs 是一个 ForBinding
          3. statusCompletion(以参数 nextValueundefinedlhs 进行的 BindingInitialization)。
      2. 否则,
        1. lhsRefCompletion(Evaluation of lhs)。(它可能被重复求值。)
        2. 如果 lhsRef突然完成,则
          1. statuslhsRef
        3. 否则,
          1. statusCompletion(PutValue(lhsRef.[[Value]], nextValue))。
    8. 否则,
      1. 断言lhsKindlexical-binding
      2. 断言lhs 是一个 ForDeclaration
      3. iterationEnvNewDeclarativeEnvironment(oldEnv)。
      4. 以参数 iterationEnvlhs 执行 ForDeclarationBindingInstantiation
      5. 设置运行执行上下文的 LexicalEnvironment 为 iterationEnv
      6. 如果 destructuringtrue,则
        1. statusCompletion(以参数 nextValueiterationEnvlhs 进行的 ForDeclarationBindingInitialization)。
      7. 否则,
        1. 断言lhs 绑定单个名称。
        2. lhsNamelhsBoundNames 的唯一元素。
        3. lhsRef 为 ! ResolveBinding(lhsName)。
        4. statusCompletion(InitializeReferencedBinding(lhsRef, nextValue))。
    9. 如果 status突然完成,则
      1. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
      2. 如果 iteratorKindasync,返回 ? AsyncIteratorClose(iteratorRecord, status)。
      3. 如果 iterationKindenumerate, 则
        1. 返回 ? status
      4. 否则,
        1. 断言iterationKinditerate
        2. 返回 ? IteratorClose(iteratorRecord, status)。
    10. resultCompletion(Evaluation of stmt)。
    11. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
    12. 如果 LoopContinues(result, labelSet) 是 false,则
      1. 如果 iterationKindenumerate, 则
        1. 返回 ? UpdateEmpty(result, V)。
      2. 否则,
        1. 断言iterationKinditerate
        2. 设置 statusCompletion(UpdateEmpty(result, V))。
        3. 如果 iteratorKindasync, 返回 ? AsyncIteratorClose(iteratorRecord, status)。
        4. 返回 ? IteratorClose(iteratorRecord, status)。
    13. 如果 result.[[Value]] 不是 empty,设置 Vresult.[[Value]]

14.7.5.8 运行时语义:Evaluation

BindingIdentifier : Identifier yield await
  1. bindingIdBindingIdentifierStringValue
  2. 返回 ? ResolveBinding(bindingId)。

14.7.5.9 EnumerateObjectProperties ( O )

抽象操作 EnumerateObjectProperties 接受参数 O(一个对象),并返回一个迭代器对象。它在被调用时执行以下步骤:

  1. 返回一个迭代器对象,其 next 方法遍历 O 的所有可枚举属性的字符串值键。该迭代器对象永远不能直接被 ECMAScript 代码访问。枚举属性的机制和顺序没有指定,但必须符合下面指定的规则。

迭代器throwreturn 方法是 null 且永远不会被调用。迭代器next 方法处理对象属性以确定属性键是否应该作为迭代器值返回。返回的属性键不包括 Symbol 键。目标对象的属性可能在枚举期间被删除。在被迭代器next 方法处理之前被删除的属性将被忽略。如果在枚举期间向目标对象添加新属性,则不保证新添加的属性会在活跃的枚举中被处理。属性名在任何枚举中最多被迭代器next 方法返回一次。

枚举目标对象的属性包括枚举其原型的属性,以及原型的原型,依此类推,递归进行;但如果原型的属性与已经被迭代器next 方法处理过的属性同名,则该原型属性不会被处理。在确定原型对象的属性是否已被处理时,不考虑 [[Enumerable]] 特性的值。原型对象的可枚举属性名必须通过调用 EnumerateObjectProperties 并传递原型对象作为参数来获得。EnumerateObjectProperties 必须通过调用目标对象的 [[OwnPropertyKeys]] 内部方法来获得目标对象的自有属性键。目标对象的属性特性必须通过调用其 [[GetOwnProperty]] 内部方法来获得。

此外,如果 O 或其原型链中的任何对象都不是代理异质对象TypedArray模块命名空间异质对象或实现提供的异质对象,则迭代器必须表现得如同由 CreateForInIterator(O) 给出的迭代器一样,直到发生以下情况之一:

  • O 或其原型链中对象的 [[Prototype]] 内部槽的值发生变化,
  • O 或其原型链中的对象删除了一个属性,
  • O 的原型链中的对象添加了一个属性,或
  • O 或其原型链中对象的属性的 [[Enumerable]] 特性值发生变化。
注 1

ECMAScript 实现不需要直接实现14.7.5.10.2.1 中的算法。它们可以选择任何实现,只要其行为不偏离该算法,除非违反了上一段中的约束之一。

以下是符合这些规则的 ECMAScript 生成器函数的信息性定义:

function* EnumerateObjectProperties(obj) {
    const visited = new Set();
    for (const key of Reflect.ownKeys(obj)) {
    if (typeof key === "symbol") continue;
    const desc = Reflect.getOwnPropertyDescriptor(obj, key);
    if (desc) {
        visited.add(key);
        if (desc.enumerable) yield key;
    }
    }
    const proto = Reflect.getPrototypeOf(obj);
    if (proto === null) return;
    for (const protoKey of EnumerateObjectProperties(proto)) {
    if (!visited.has(protoKey)) yield protoKey;
    }
}
注 2
选择不要求实现匹配 CreateForInIterator异质对象列表,是因为历史上实现在这些情况下的行为有所不同,而在所有其他情况下是一致的。

14.7.5.10 For-In 迭代器对象

For-In 迭代器是表示对某个特定对象进行特定迭代的对象。For-In 迭代器对象永远不能直接被 ECMAScript 代码访问;它们只是为了说明 EnumerateObjectProperties 的行为而存在。

14.7.5.10.1 CreateForInIterator ( object )

抽象操作 CreateForInIterator 接受参数 object(一个对象),并返回一个 For-In 迭代器。它用于创建一个 For-In 迭代器对象,该对象以特定顺序遍历 object 的自有和继承的可枚举字符串属性。它在被调用时执行以下步骤:

  1. iteratorOrdinaryObjectCreate(%ForInIteratorPrototype%, « [[Object]], [[ObjectWasVisited]], [[VisitedKeys]], [[RemainingKeys]] »)。
  2. 设置 iterator.[[Object]]object
  3. 设置 iterator.[[ObjectWasVisited]]false
  4. 设置 iterator.[[VisitedKeys]] 为一个新的空列表
  5. 设置 iterator.[[RemainingKeys]] 为一个新的空列表
  6. 返回 iterator

14.7.5.10.2 %ForInIteratorPrototype% 对象

%ForInIteratorPrototype% 对象:

14.7.5.10.2.1 %ForInIteratorPrototype%.next ( )

  1. Othis 值。
  2. 断言O 是对象
  3. 断言O 具有 For-In 迭代器实例的所有内部槽(14.7.5.10.3)。
  4. objectO.[[Object]]
  5. 重复,
    1. 如果 O.[[ObjectWasVisited]]false,则
      1. keys 为 ? object.[[OwnPropertyKeys]]()
      2. keys 的每个元素 key,执行
        1. 如果 key 是字符串,则
          1. key 追加到 O.[[RemainingKeys]]
      3. 设置 O.[[ObjectWasVisited]]true
    2. 重复,当 O.[[RemainingKeys]] 不为空时,
      1. rO.[[RemainingKeys]] 的第一个元素。
      2. O.[[RemainingKeys]] 中移除第一个元素。
      3. 如果 O.[[VisitedKeys]] 不包含 r,则
        1. desc 为 ? object.[[GetOwnProperty]](r)。
        2. 如果 desc 不是 undefined,则
          1. r 追加到 O.[[VisitedKeys]]
          2. 如果 desc.[[Enumerable]]true,返回 CreateIteratorResultObject(r, false)。
    3. 设置 object 为 ? object.[[GetPrototypeOf]]()
    4. 设置 O.[[Object]]object
    5. 设置 O.[[ObjectWasVisited]]false
    6. 如果 objectnull,返回 CreateIteratorResultObject(undefined, true)。

14.7.5.10.3 For-In 迭代器实例的属性

For-In 迭代器实例是普通对象,它们从 %ForInIteratorPrototype% 内在对象继承属性。For-In 迭代器实例最初使用 表 38 中列出的内部槽创建。

表 38:For-In 迭代器实例的内部槽
内部槽 类型 描述
[[Object]] 一个对象 正在迭代其属性的对象值。
[[ObjectWasVisited]] 一个布尔值 如果迭代器已在 [[Object]] 上调用了 [[OwnPropertyKeys]],则为 true,否则为 false
[[VisitedKeys]] 一个包含字符串的列表 到目前为止已被此迭代器发出的值。
[[RemainingKeys]] 一个包含字符串的列表 在迭代其原型的属性之前(如果其原型不是 null),当前对象剩余要发出的值。

14.8 continue 语句

语法

ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.8.1 静态语义:早期错误

ContinueStatement : continue ; continue LabelIdentifier ;

14.8.2 运行时语义:Evaluation

ContinueStatement : continue ;
  1. 返回 完成记录 { [[Type]]: continue, [[Value]]: empty, [[Target]]: empty }。
ContinueStatement : continue LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 完成记录 { [[Type]]: continue, [[Value]]: empty, [[Target]]: label }。

14.9 break 语句

语法

BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ;

14.9.1 静态语义:早期错误

BreakStatement : break ;

14.9.2 运行时语义:Evaluation

BreakStatement : break ;
  1. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: empty }。
BreakStatement : break LabelIdentifier ;
  1. labelLabelIdentifierStringValue
  2. 返回 完成记录 { [[Type]]: break, [[Value]]: empty, [[Target]]: label }。

14.10 return 语句

语法

ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

return 语句使函数停止执行,并且在大多数情况下将值返回给调用者。如果省略了 Expression,则返回值是 undefined。否则,返回值是 Expression 的值。根据周围的上下文,return 语句可能实际上不会将值返回给调用者。例如,在 try 块中,return 语句的完成记录可能在对 finally 块进行求值期间被另一个完成记录替换。

14.10.1 运行时语义:Evaluation

ReturnStatement : return ;
  1. 返回 ReturnCompletion(undefined)。
ReturnStatement : return Expression ;
  1. exprRef 为 ? Evaluation of Expression
  2. exprValue 为 ? GetValue(exprRef)。
  3. 如果 GetGeneratorKind() 是 async,设置 exprValue 为 ? Await(exprValue)。
  4. 返回 ReturnCompletion(exprValue)。

14.11 with 语句

注 1

不鼓励在新的 ECMAScript 代码中使用Legacy with 语句。考虑在严格模式代码非严格代码中都允许的替代方案,例如解构赋值

语法

WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] 注 2

with 语句将计算对象的对象环境记录添加到运行执行上下文的词法环境中。然后使用这个增强的词法环境执行语句。最后,恢复原始的词法环境。

14.11.1 静态语义:早期错误

WithStatement : with ( Expression ) Statement

只有在实现了B.3.1 中指定的扩展时,才需要应用第二条规则。

14.11.2 运行时语义:Evaluation

WithStatement : with ( Expression ) Statement
  1. val 为 ? Evaluation of Expression
  2. obj 为 ? ToObject(? GetValue(val))。
  3. oldEnv运行执行上下文的 LexicalEnvironment。
  4. newEnvNewObjectEnvironment(obj, true, oldEnv)。
  5. 设置运行执行上下文的 LexicalEnvironment 为 newEnv
  6. CCompletion(Evaluation of Statement)。
  7. 设置运行执行上下文的 LexicalEnvironment 为 oldEnv
  8. 返回 ? UpdateEmpty(C, undefined)。

无论控制如何离开嵌入的 Statement,无论是正常方式还是通过某种形式的突然完成或异常,LexicalEnvironment 总是恢复到其原来的状态。

14.12 switch 语句

语法

SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt

14.12.1 静态语义:早期错误

SwitchStatement : switch ( Expression ) CaseBlock

14.12.2 运行时语义:CaseBlockEvaluation

语法制导操作 CaseBlockEvaluation 接受参数 input(一个 ECMAScript 语言值)并 返回一个 包含 ECMAScript 语言值正常完成突然完成。它按以下产生式分段定义:

CaseBlock : { }
  1. 返回 undefined
CaseBlock : { CaseClauses }
  1. Vundefined
  2. ACaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  3. foundfalse
  4. 对于 A 中的每个 CaseClause C,执行
    1. 如果 foundfalse,则
      1. 设置 found 为 ? CaseClauseIsSelected(C, input)。
    2. 如果 foundtrue,则
      1. RCompletion(Evaluation of C)。
      2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
      3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  5. 返回 V
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. Vundefined
  2. 如果第一个 CaseClauses 存在,则
    1. A 为第一个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  3. 否则,
    1. A 为一个新的空 列表
  4. foundfalse
  5. 对于 A 中的每个 CaseClause C,执行
    1. 如果 foundfalse,则
      1. 设置 found 为 ? CaseClauseIsSelected(C, input)。
    2. 如果 foundtrue,则
      1. RCompletion(Evaluation of C)。
      2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
      3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  6. foundInBfalse
  7. 如果第二个 CaseClauses 存在,则
    1. B 为第二个 CaseClauses 中按源文本顺序排列的 CaseClause 项的 列表
  8. 否则,
    1. B 为一个新的空 列表
  9. 如果 foundfalse,则
    1. 对于 B 中的每个 CaseClause C,执行
      1. 如果 foundInBfalse,则
        1. 设置 foundInB 为 ? CaseClauseIsSelected(C, input)。
      2. 如果 foundInBtrue,则
        1. RCompletion(Evaluation of CaseClause C)。
        2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
        3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  10. 如果 foundInBtrue,返回 V
  11. defaultRCompletion(Evaluation of DefaultClause)。
  12. 如果 defaultR.[[Value]] 不是 empty,设置 VdefaultR.[[Value]]
  13. 如果 defaultR突然完成,返回 ? UpdateEmpty(defaultR, V)。
  14. 注:以下是对第二个 CaseClauses 的另一次完整迭代。
  15. 对于 B 中的每个 CaseClause C,执行
    1. RCompletion(Evaluation of CaseClause C)。
    2. 如果 R.[[Value]] 不是 empty,设置 VR.[[Value]]
    3. 如果 R突然完成,返回 ? UpdateEmpty(R, V)。
  16. 返回 V

14.12.3 CaseClauseIsSelected ( C, input )

抽象操作 CaseClauseIsSelected 接受参数 C(一个 CaseClause 解析节点)和 input(一个 ECMAScript 语言值)并 返回一个 包含 Boolean 的 正常完成突然完成。它 确定 C 是否匹配 input。调用时执行以下步骤:

  1. 断言C 是产生式 CaseClause : case Expression : StatementListopt 的实例。
  2. exprRef 为 ? Evaluation of CExpression
  3. clauseSelector 为 ? GetValue(exprRef)。
  4. 返回 IsStrictlyEqual(input, clauseSelector)。

此操作不执行 CStatementList(如果有)。CaseBlock 算法使用其 返回值来确定从哪个 StatementList 开始执行。

14.12.4 运行时语义:Evaluation

SwitchStatement : switch ( Expression ) CaseBlock
  1. exprRef 为 ? Evaluation of Expression
  2. switchValue 为 ? GetValue(exprRef)。
  3. oldEnv运行执行上下文 的 LexicalEnvironment。
  4. blockEnvNewDeclarativeEnvironment(oldEnv)。
  5. 执行 BlockDeclarationInstantiation(CaseBlock, blockEnv)。
  6. 设置 运行执行上下文 的 LexicalEnvironment 为 blockEnv
  7. RCompletion(CaseBlockEvaluation of CaseBlock with argument switchValue)。
  8. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
  9. 返回 R

无论控制如何离开 SwitchStatement,LexicalEnvironment 总是恢复到之前的状态。

CaseClause : case Expression :
  1. 返回 empty
CaseClause : case Expression : StatementList
  1. 返回 ? Evaluation of StatementList
DefaultClause : default :
  1. 返回 empty
DefaultClause : default : StatementList
  1. 返回 ? Evaluation of StatementList

14.13 标签语句

语法

LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default]

一个 Statement 可以用标签作为前缀。标签语句只与带标签的 breakcontinue 语句结合使用。ECMAScript 没有 goto 语句。一个 Statement 可以是 LabelledStatement 的一部分, 而它本身又可以是另一个 LabelledStatement 的一部分,以此类推。以这种方式引入的标签在描述各个语句的语义时统称为"当前标签集"。

14.13.1 静态语义:早期错误

LabelledItem : FunctionDeclaration
  • 如果任何源文本匹配此产生式,则是语法错误。

此规则的替代定义在 B.3.1 中提供。

14.13.2 静态语义:IsLabelledFunction ( stmt )

抽象操作 IsLabelledFunction 接受参数 stmt(一个 Statement 解析节点)并返回一个 Boolean。调用时执行以下步骤:

  1. 如果 stmt 不是 LabelledStatement,返回 false
  2. itemstmtLabelledItem
  3. 如果 item LabelledItem : FunctionDeclaration ,返回 true
  4. subStmtitemStatement
  5. 返回 IsLabelledFunction(subStmt)。

14.13.3 运行时语义:Evaluation

LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 ? LabelledEvaluation of this LabelledStatement with argument « »。

14.13.4 运行时语义:LabelledEvaluation

语法制导操作 LabelledEvaluation 接受参数 labelSet(一个 字符串的 列表)并 返回一个 包含 ECMAScript 语言值empty正常完成,或 突然完成。它按以下产生式分段定义:

BreakableStatement : IterationStatement
  1. stmtResultCompletion(LoopEvaluation of IterationStatement with argument labelSet)。
  2. 如果 stmtResultbreak 完成,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,设置 stmtResultNormalCompletion(undefined)。
      2. 否则,设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
BreakableStatement : SwitchStatement
  1. stmtResultCompletion(Evaluation of SwitchStatement)。
  2. 如果 stmtResultbreak 完成,则
    1. 如果 stmtResult.[[Target]]empty,则
      1. 如果 stmtResult.[[Value]]empty,设置 stmtResultNormalCompletion(undefined)。
      2. 否则,设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  3. 返回 ? stmtResult
注 1

BreakableStatement 是可以通过无标签的 BreakStatement 退出的语句。

LabelledStatement : LabelIdentifier : LabelledItem
  1. labelLabelIdentifierStringValue
  2. newLabelSetlabelSet 和 « label » 的 列表连接
  3. stmtResultCompletion(LabelledEvaluation of LabelledItem with argument newLabelSet)。
  4. 如果 stmtResultbreak 完成stmtResult.[[Target]]label,则
    1. 设置 stmtResultNormalCompletion(stmtResult.[[Value]])。
  5. 返回 ? stmtResult
LabelledItem : FunctionDeclaration
  1. 返回 ? Evaluation of FunctionDeclaration
Statement : BlockStatement VariableStatement EmptyStatement ExpressionStatement IfStatement ContinueStatement BreakStatement ReturnStatement WithStatement ThrowStatement TryStatement DebuggerStatement
  1. 返回 ? Evaluation of Statement
注 2

Statement 中仅有两个产生式对 LabelledEvaluation 具有特殊语义:BreakableStatementLabelledStatement

14.14 throw 语句

语法

ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ;

14.14.1 运行时语义:Evaluation

ThrowStatement : throw Expression ;
  1. exprRef 为 ? Evaluation of Expression
  2. exprValue 为 ? GetValue(exprRef)。
  3. 返回 ThrowCompletion(exprValue)。

14.15 try 语句

语法

TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await]

try 语句包含一个可能发生异常情况的代码块,比如运行时错误或 throw 语句。catch 子句提供异常处理代码。当 catch 子句捕获异常时,其 CatchParameter 绑定到该异常。

14.15.1 静态语义:早期错误

Catch : catch ( CatchParameter ) Block

此产生式的替代 静态语义B.3.4 中给出。

14.15.2 运行时语义:CatchClauseEvaluation

语法制导操作 CatchClauseEvaluation 接受参数 thrownValue(一个 ECMAScript 语言值)并 返回一个 包含 ECMAScript 语言值empty正常完成,或 突然完成。它按以下产生式分段定义:

Catch : catch ( CatchParameter ) Block
  1. oldEnv运行执行上下文 的 LexicalEnvironment。
  2. catchEnvNewDeclarativeEnvironment(oldEnv)。
  3. 对于 CatchParameterBoundNames 中的每个元素 argName,执行
    1. 执行 ! catchEnv.CreateMutableBinding(argName, false)。
  4. 设置 运行执行上下文 的 LexicalEnvironment 为 catchEnv
  5. statusCompletion(BindingInitialization of CatchParameter with arguments thrownValue and catchEnv)。
  6. 如果 status突然完成,则
    1. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
    2. 返回 ? status
  7. BCompletion(Evaluation of Block)。
  8. 设置 运行执行上下文 的 LexicalEnvironment 为 oldEnv
  9. 返回 ? B
Catch : catch Block
  1. 返回 ? Evaluation of Block

无论控制如何离开 Block,LexicalEnvironment 总是恢复到之前的状态。

14.15.3 运行时语义:Evaluation

TryStatement : try Block Catch
  1. BCompletion(Evaluation of Block)。
  2. 如果 Bthrow 完成,令 CCompletion(CatchClauseEvaluation of Catch with argument B.[[Value]])。
  3. 否则,令 CB
  4. 返回 ? UpdateEmpty(C, undefined)。
TryStatement : try Block Finally
  1. BCompletion(Evaluation of Block)。
  2. FCompletion(Evaluation of Finally)。
  3. 如果 F正常完成,设置 FB
  4. 返回 ? UpdateEmpty(F, undefined)。
TryStatement : try Block Catch Finally
  1. BCompletion(Evaluation of Block)。
  2. 如果 Bthrow 完成,令 CCompletion(CatchClauseEvaluation of Catch with argument B.[[Value]])。
  3. 否则,令 CB
  4. FCompletion(Evaluation of Finally)。
  5. 如果 F正常完成,设置 FC
  6. 返回 ? UpdateEmpty(F, undefined)。

14.16 debugger 语句

语法

DebuggerStatement : debugger ;

14.16.1 运行时语义:Evaluation

计算 DebuggerStatement 可能允许实现在调试器下运行时触发断点。如果调试器不存在或不活跃,此语句没有可观察的效果。

DebuggerStatement : debugger ;
  1. 如果 实现定义的 调试设施可用且已启用,则
    1. 执行 实现定义的 调试动作。
    2. 返回一个新的 实现定义的 完成记录
  2. 否则,
    1. 返回 empty

15 ECMAScript 语言:函数和类

各种 ECMAScript 语言元素会导致创建 ECMAScript 函数对象10.2)。这些函数的 Evaluation 从执行其 [[Call]] 内部方法开始(10.2.1)。

15.1 参数列表

语法

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await]

15.1.1 静态语义:早期错误

UniqueFormalParameters : FormalParameters FormalParameters : FormalParameterList

相同 BindingIdentifierFormalParameterList 中的多次出现 只允许出现在具有简单参数列表且未在 严格模式代码 中定义的函数中。

15.1.2 静态语义:ContainsExpression

语法制导操作 ContainsExpression 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

ObjectBindingPattern : { } { BindingRestProperty }
  1. 返回 false
ObjectBindingPattern : { BindingPropertyList , BindingRestProperty }
  1. 返回 BindingPropertyListContainsExpression
ArrayBindingPattern : [ Elisionopt ]
  1. 返回 false
ArrayBindingPattern : [ Elisionopt BindingRestElement ]
  1. 返回 BindingRestElementContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt ]
  1. 返回 BindingElementListContainsExpression
ArrayBindingPattern : [ BindingElementList , Elisionopt BindingRestElement ]
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingRestElementContainsExpression
BindingPropertyList : BindingPropertyList , BindingProperty
  1. hasBindingPropertyListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingPropertyContainsExpression
BindingElementList : BindingElementList , BindingElisionElement
  1. hasBindingElementListContainsExpression
  2. 如果 hastrue,返回 true
  3. 返回 BindingElisionElementContainsExpression
BindingElisionElement : Elisionopt BindingElement
  1. 返回 BindingElementContainsExpression
BindingProperty : PropertyName : BindingElement
  1. hasPropertyNameIsComputedPropertyKey
  2. 如果 hastrue,返回 true
  3. 返回 BindingElementContainsExpression
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
BindingRestElement : ... BindingIdentifier
  1. 返回 false
BindingRestElement : ... BindingPattern
  1. 返回 BindingPatternContainsExpression
FormalParameters : [empty]
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 如果 FormalParameterListContainsExpressiontrue,返回 true
  2. 返回 FunctionRestParameterContainsExpression
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListContainsExpressiontrue,返回 true
  2. 返回 FormalParameterContainsExpression
ArrowParameters : BindingIdentifier
  1. 返回 false
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsContainsExpression
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 false

15.1.3 静态语义:IsSimpleParameterList

语法制导操作 IsSimpleParameterList 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 false
SingleNameBinding : BindingIdentifier
  1. 返回 true
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 false
FormalParameters : [empty]
  1. 返回 true
FormalParameters : FunctionRestParameter
  1. 返回 false
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 false
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListIsSimpleParameterListfalse,返回 false
  2. 返回 FormalParameterIsSimpleParameterList
FormalParameter : BindingElement
  1. 返回 BindingElementIsSimpleParameterList
ArrowParameters : BindingIdentifier
  1. 返回 true
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsIsSimpleParameterList
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 true
CoverCallExpressionAndAsyncArrowHead : MemberExpression Arguments
  1. head 为由 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  2. 返回 headIsSimpleParameterList

15.1.4 静态语义:HasInitializer

语法制导操作 HasInitializer 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

BindingElement : BindingPattern
  1. 返回 false
BindingElement : BindingPattern Initializer
  1. 返回 true
SingleNameBinding : BindingIdentifier
  1. 返回 false
SingleNameBinding : BindingIdentifier Initializer
  1. 返回 true
FormalParameterList : FormalParameterList , FormalParameter
  1. 如果 FormalParameterListHasInitializertrue,返回 true
  2. 返回 FormalParameterHasInitializer

15.1.5 静态语义:ExpectedArgumentCount

语法制导操作 ExpectedArgumentCount 不接受参数并返回一个非负 整数。它按以下产生式分段定义:

FormalParameters : [empty] FunctionRestParameter
  1. 返回 0。
FormalParameters : FormalParameterList , FunctionRestParameter
  1. 返回 FormalParameterListExpectedArgumentCount

FormalParameterList 的 ExpectedArgumentCount 是在剩余参数或第一个具有初始化器的 FormalParameter 左侧的 FormalParameters 的数量。没有初始化器的 FormalParameter 可以出现在第一个有初始化器的参数之后,但这样的参数被认为是可选的,其默认值为 undefined

FormalParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,返回 0。
  2. 返回 1。
FormalParameterList : FormalParameterList , FormalParameter
  1. countFormalParameterListExpectedArgumentCount
  2. 如果 FormalParameterListHasInitializertrueFormalParameterHasInitializertrue,返回 count
  3. 返回 count + 1。
ArrowParameters : BindingIdentifier
  1. 返回 1。
ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList
  1. formals 为由 CoverParenthesizedExpressionAndArrowParameterList 覆盖ArrowFormalParameters
  2. 返回 formalsExpectedArgumentCount
PropertySetParameterList : FormalParameter
  1. 如果 FormalParameterHasInitializertrue,返回 0。
  2. 返回 1。
AsyncArrowBindingIdentifier : BindingIdentifier
  1. 返回 1。

15.2 函数定义

语法

FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt

15.2.1 静态语义:早期错误

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }

FunctionBodyLexicallyDeclaredNames 不包括使用 var 或 function 声明绑定的标识符。

FunctionBody : FunctionStatementList

15.2.2 静态语义:FunctionBodyContainsUseStrict

语法制导操作 FunctionBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

FunctionBody : FunctionStatementList
  1. 如果 FunctionBody指令序言 包含一个 Use Strict 指令,返回 true;否则,返回 false

15.2.3 运行时语义:EvaluateFunctionBody

语法制导操作 EvaluateFunctionBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 ECMAScript 语言值List)并返回一个 return completionthrow completion。它按以下产生式分段定义:

FunctionBody : FunctionStatementList
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 执行 ? Evaluation of FunctionStatementList
  3. 注:如果前面的步骤产生了一个 normal completion,那么求值通过继续执行到 FunctionStatementList 的末尾而结束。
  4. 返回 ReturnCompletion(undefined)。

15.2.4 运行时语义:InstantiateOrdinaryFunctionObject

语法制导操作 InstantiateOrdinaryFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextFunctionDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. 执行 MakeConstructor(F)。
  6. 返回 F
FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. sourceTextFunctionDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. 执行 MakeConstructor(F)。
  5. 返回 F

匿名 FunctionDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码总是 严格模式代码

15.2.5 运行时语义:InstantiateOrdinaryFunctionExpression

语法制导操作 InstantiateOrdinaryFunctionExpression 接受可选参数 name(一个 属性键私有名称)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

FunctionExpression : function ( FormalParameters ) { FunctionBody }
  1. 如果不存在 name,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 执行 MakeConstructor(closure)。
  8. 返回 closure
FunctionExpression : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextFunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, FormalParameters, FunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 MakeConstructor(closure)。
  11. 执行 ! funcEnv.InitializeBinding(name, closure)。
  12. 返回 closure

FunctionExpression 中的 BindingIdentifier 可以从 FunctionExpressionFunctionBody 内部引用,以允许函数递归地调用自身。然而,与 FunctionDeclaration 不同,FunctionExpression 中的 BindingIdentifier 不能从包围 FunctionExpression 的作用域中引用,也不会影响该作用域。

15.2.6 运行时语义:Evaluation

FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody }
  1. 返回 empty
注 1

B.3.2 中提供了替代语义。

FunctionDeclaration : function ( FormalParameters ) { FunctionBody }
  1. 返回 empty
FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody }
  1. 返回 FunctionExpressionInstantiateOrdinaryFunctionExpression
注 2

对于使用 FunctionDeclarationFunctionExpression 定义的每个函数,都会自动创建一个 "prototype" 属性,以允许该函数被用作 构造函数

FunctionStatementList : [empty]
  1. 返回 undefined

15.3 箭头函数定义

语法

ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

补充语法

当处理产生式的实例
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
时,CoverParenthesizedExpressionAndArrowParameterList 的解释使用以下语法进行细化:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

15.3.1 静态语义:早期错误

ArrowFunction : ArrowParameters => ConciseBody ArrowParameters : CoverParenthesizedExpressionAndArrowParameterList

15.3.2 静态语义:ConciseBodyContainsUseStrict

语法制导操作 ConciseBodyContainsUseStrict 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

ConciseBody : ExpressionBody
  1. 返回 false
ConciseBody : { FunctionBody }
  1. 返回 FunctionBodyFunctionBodyContainsUseStrict

15.3.3 运行时语义:EvaluateConciseBody

语法制导操作 EvaluateConciseBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 ECMAScript 语言值List)并返回一个 return completionthrow completion。它按以下产生式分段定义:

ConciseBody : ExpressionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. 返回 ? Evaluation of ExpressionBody

15.3.4 运行时语义:InstantiateArrowFunctionExpression

语法制导操作 InstantiateArrowFunctionExpression 接受可选参数 name(一个 属性键私有名称)并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

ArrowFunction : ArrowParameters => ConciseBody
  1. 如果不存在 name,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextArrowFunction 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, ArrowParameters, ConciseBody, lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure

ArrowFunction 不为 argumentssuperthisnew.target 定义局部绑定。ArrowFunction 内对 argumentssuperthisnew.target 的任何引用都必须解析为词法封闭环境中的绑定。通常这会是紧邻封闭函数的函数环境。尽管 ArrowFunction 可能包含对 super 的引用,但在步骤 5 中创建的 函数对象 不会通过执行 MakeMethod 而成为方法。引用 superArrowFunction 总是包含在非 ArrowFunction 中,实现 super 所需的状态可以通过被 ArrowFunction函数对象 捕获的 env 访问。

15.3.5 运行时语义:Evaluation

ArrowFunction : ArrowParameters => ConciseBody
  1. 返回 ArrowFunctionInstantiateArrowFunctionExpression
ExpressionBody : AssignmentExpression
  1. exprRef 为 ? Evaluation of AssignmentExpression
  2. exprValue 为 ? GetValue(exprRef)。
  3. 返回 ReturnCompletion(exprValue)。

15.4 方法定义

语法

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await]

15.4.1 静态语义:早期错误

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }

15.4.2 静态语义:HasDirectSuper

语法制导操作 HasDirectSuper 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 FunctionBody Contains SuperCall
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. 返回 FunctionBody Contains SuperCall
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 如果 PropertySetParameterList Contains SuperCalltrue,返回 true
  2. 返回 FunctionBody Contains SuperCall
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 GeneratorBody Contains SuperCall
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 AsyncGeneratorBody Contains SuperCall
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 如果 UniqueFormalParameters Contains SuperCalltrue,返回 true
  2. 返回 AsyncFunctionBody Contains SuperCall

15.4.3 静态语义:SpecialMethod

语法制导操作 SpecialMethod 不接受参数并返回一个 Boolean。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. 返回 false
MethodDefinition : GeneratorMethod AsyncMethod AsyncGeneratorMethod get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. 返回 true

15.4.4 运行时语义:DefineMethod

语法制导操作 DefineMethod 接受参数 object(一个 Object)和可选参数 functionPrototype(一个 Object)并返回 包含一个 Record(字段为 [[Key]](一个 属性键)和 [[Closure]](一个 ECMAScript 函数对象))的 normal completionabrupt completion。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. 如果存在 functionPrototype,那么
    1. prototypefunctionPrototype
  5. 否则,
    1. prototype%Function.prototype%
  6. sourceTextMethodDefinition 匹配的源文本
  7. closureOrdinaryFunctionCreate(prototype, sourceText, UniqueFormalParameters, FunctionBody, non-lexical-this, env, privateEnv)。
  8. 执行 MakeMethod(closure, object)。
  9. 返回 Record { [[Key]]: propKey, [[Closure]]: closure }。

15.4.5 运行时语义:MethodDefinitionEvaluation

语法制导操作 MethodDefinitionEvaluation 接受参数 object(一个 Object)和 enumerable(一个 Boolean)并返回 包含 PrivateElementunusednormal completion,或 abrupt completion。它按以下产生式分段定义:

MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody }
  1. methodDefMethodDefinition 以参数 object 的 ? DefineMethod
  2. 执行 SetFunctionName(methodDef.[[Closure]], methodDef.[[Key]])。
  3. 返回 ? DefineMethodProperty(object, methodDef.[[Key]], methodDef.[[Closure]], enumerable)。
MethodDefinition : get ClassElementName ( ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextMethodDefinition 匹配的源文本
  5. formalParameterList 为产生式 FormalParameters : [empty] 的实例。
  6. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  7. 执行 MakeMethod(closure, object)。
  8. 执行 SetFunctionName(closure, propKey, "get")。
  9. 如果 propKey私有名称,那么
    1. 返回 PrivateElement { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: closure, [[Set]]: undefined }。
  10. 否则,
    1. desc 为 PropertyDescriptor { [[Get]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(object, propKey, desc)。
    3. 返回 unused
MethodDefinition : set ClassElementName ( PropertySetParameterList ) { FunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextMethodDefinition 匹配的源文本
  5. closureOrdinaryFunctionCreate(%Function.prototype%, sourceText, PropertySetParameterList, FunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey, "set")。
  8. 如果 propKey私有名称,那么
    1. 返回 PrivateElement { [[Key]]: propKey, [[Kind]]: accessor, [[Get]]: undefined, [[Set]]: closure }。
  9. 否则,
    1. desc 为 PropertyDescriptor { [[Set]]: closure, [[Enumerable]]: enumerable, [[Configurable]]: true }。
    2. 执行 ? DefinePropertyOrThrow(object, propKey, desc)。
    3. 返回 unused
GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextGeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, UniqueFormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。
AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, UniqueFormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  9. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  10. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。
AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. propKey 为 ? Evaluation of ClassElementName
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncMethod 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, UniqueFormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 MakeMethod(closure, object)。
  7. 执行 SetFunctionName(closure, propKey)。
  8. 返回 ? DefineMethodProperty(object, propKey, closure, enumerable)。

15.5 生成器函数定义

语法

GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] 注 1

紧跟在 yield 后面的语法上下文需要使用 InputElementRegExpOrTemplateTail 词法目标。

注 2

YieldExpression 不能在生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都在生成的 Generator 处于可恢复状态之前被求值。

注 3

与 Generators 相关的 抽象操作27.5.3 中定义。

15.5.1 静态语义:早期错误

GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }

15.5.2 运行时语义:EvaluateGeneratorBody

语法制导操作 EvaluateGeneratorBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),并返回 throw completionreturn completion。它按以下产生式分段定义:

GeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. G 为 ? OrdinaryCreateFromConstructor(functionObject, "%GeneratorPrototype%", « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] »)。
  3. 设置 G.[[GeneratorBrand]]empty
  4. 设置 G.[[GeneratorState]]suspended-start
  5. 执行 GeneratorStart(G, FunctionBody)。
  6. 返回 ReturnCompletion(G)。

15.5.3 运行时语义:InstantiateGeneratorFunctionObject

语法制导操作 InstantiateGeneratorFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextGeneratorDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 F
GeneratorDeclaration : function * ( FormalParameters ) { GeneratorBody }
  1. sourceTextGeneratorDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 F

匿名的 GeneratorDeclaration 只能作为 export default 声明的一部分出现,因此其函数代码总是 严格模式代码

15.5.4 运行时语义:InstantiateGeneratorFunctionExpression

语法制导操作 InstantiateGeneratorFunctionExpression 接受可选参数 name(一个 属性键私有名称),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

GeneratorExpression : function * ( FormalParameters ) { GeneratorBody }
  1. 如果 name 不存在,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextGeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
GeneratorExpression : function * BindingIdentifier ( FormalParameters ) { GeneratorBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextGeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%GeneratorFunction.prototype%, sourceText, FormalParameters, GeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
注释

GeneratorExpression 中的 BindingIdentifier 可以从 GeneratorExpressionFunctionBody 内部引用,以允许生成器代码递归调用自身。然而,与 GeneratorDeclaration 不同,GeneratorExpression 中的 BindingIdentifier 不能从包围 GeneratorExpression 的作用域中引用,也不会影响该作用域。

15.5.5 运行时语义:Evaluation

GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }
  1. 返回 GeneratorExpressionInstantiateGeneratorFunctionExpression
YieldExpression : yield
  1. 返回 ? Yield(undefined)。
YieldExpression : yield AssignmentExpression
  1. exprRef 为 ? Evaluation of AssignmentExpression
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Yield(value)。
YieldExpression : yield * AssignmentExpression
  1. generatorKindGetGeneratorKind()。
  2. 断言generatorKindsyncasync
  3. exprRef 为 ? Evaluation of AssignmentExpression
  4. value 为 ? GetValue(exprRef)。
  5. iteratorRecord 为 ? GetIterator(value, generatorKind)。
  6. iteratoriteratorRecord.[[Iterator]]
  7. receivedNormalCompletion(undefined)。
  8. 重复,
    1. 如果 received 是一个 normal completion,那么
      1. innerResult 为 ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]], « received.[[Value]] »)。
      2. 如果 generatorKindasync,设置 innerResult 为 ? Await(innerResult)。
      3. 如果 innerResult 不是 Object,抛出 TypeError 异常。
      4. done 为 ? IteratorComplete(innerResult)。
      5. 如果 donetrue,那么
        1. 返回 ? IteratorValue(innerResult)。
      6. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
      7. 否则,设置 receivedCompletion(GeneratorYield(innerResult))。
    2. 否则如果 received 是一个 throw completion,那么
      1. throw 为 ? GetMethod(iterator, "throw")。
      2. 如果 throw 不是 undefined,那么
        1. innerResult 为 ? Call(throw, iterator, « received.[[Value]] »)。
        2. 如果 generatorKindasync,设置 innerResult 为 ? Await(innerResult)。
        3. 注释:来自内部 迭代器 throw 方法的异常会被传播。来自内部 throw 方法的 Normal completion 的处理方式与内部 next 类似。
        4. 如果 innerResult 不是 Object,抛出 TypeError 异常。
        5. done 为 ? IteratorComplete(innerResult)。
        6. 如果 donetrue,那么
          1. 返回 ? IteratorValue(innerResult)。
        7. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerResult)))。
        8. 否则,设置 receivedCompletion(GeneratorYield(innerResult))。
      3. 否则,
        1. 注释:如果 iterator 没有 throw 方法,这个 throw 将终止 yield* 循环。但首先我们需要给 iterator 一个清理的机会。
        2. closeCompletionNormalCompletion(empty)。
        3. 如果 generatorKindasync,执行 ? AsyncIteratorClose(iteratorRecord, closeCompletion)。
        4. 否则,执行 ? IteratorClose(iteratorRecord, closeCompletion)。
        5. 注释:下一步抛出 TypeError 表示存在 yield* 协议违反:iterator 没有 throw 方法。
        6. 抛出 TypeError 异常。
    3. 否则,
      1. 断言received 是一个 return completion
      2. return 为 ? GetMethod(iterator, "return")。
      3. 如果 returnundefined,那么
        1. 设置 valuereceived.[[Value]]
        2. 如果 generatorKindasync,那么
          1. 设置 value 为 ? Await(value)。
        3. 返回 ReturnCompletion(value)。
      4. innerReturnResult 为 ? Call(return, iterator, « received.[[Value]] »)。
      5. 如果 generatorKindasync,设置 innerReturnResult 为 ? Await(innerReturnResult)。
      6. 如果 innerReturnResult 不是 Object,抛出 TypeError 异常。
      7. done 为 ? IteratorComplete(innerReturnResult)。
      8. 如果 donetrue,那么
        1. 设置 value 为 ? IteratorValue(innerReturnResult)。
        2. 返回 ReturnCompletion(value)。
      9. 如果 generatorKindasync,设置 receivedCompletion(AsyncGeneratorYield(? IteratorValue(innerReturnResult)))。
      10. 否则,设置 receivedCompletion(GeneratorYield(innerReturnResult))。

15.6 异步生成器函数定义

语法

AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] 注释 1

YieldExpressionAwaitExpression 不能在异步生成器函数的 FormalParameters 中使用,因为作为 FormalParameters 一部分的任何表达式都在生成的 AsyncGenerator 处于可恢复状态之前被求值。

注释 2

与 AsyncGenerators 相关的 抽象操作27.6.3 中定义。

15.6.1 静态语义:早期错误

AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }

15.6.2 运行时语义:EvaluateAsyncGeneratorBody

语法制导操作 EvaluateAsyncGeneratorBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),并返回 throw completionreturn completion。它按以下产生式分段定义:

AsyncGeneratorBody : FunctionBody
  1. 执行 ? FunctionDeclarationInstantiation(functionObject, argumentsList)。
  2. generator 为 ? OrdinaryCreateFromConstructor(functionObject, "%AsyncGeneratorPrototype%", « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] »)。
  3. 设置 generator.[[GeneratorBrand]]empty
  4. 设置 generator.[[AsyncGeneratorState]]suspended-start
  5. 执行 AsyncGeneratorStart(generator, FunctionBody)。
  6. 返回 ReturnCompletion(generator)。

15.6.3 运行时语义:InstantiateAsyncGeneratorFunctionObject

语法制导操作 InstantiateAsyncGeneratorFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncGeneratorDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  6. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  7. 返回 F
AsyncGeneratorDeclaration : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. sourceTextAsyncGeneratorDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  5. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  6. 返回 F
注释

匿名的 AsyncGeneratorDeclaration 只能作为 export default 声明的一部分出现。

15.6.4 运行时语义:InstantiateAsyncGeneratorFunctionExpression

语法制导操作 InstantiateAsyncGeneratorFunctionExpression 接受可选参数 name(一个 属性键私有名称),并返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncGeneratorExpression : async function * ( FormalParameters ) { AsyncGeneratorBody }
  1. 如果 name 不存在,设置 name""
  2. env运行执行上下文 的 LexicalEnvironment。
  3. privateEnv运行执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncGeneratorExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  8. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  9. 返回 closure
AsyncGeneratorExpression : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv运行执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv运行执行上下文 的 PrivateEnvironment。
  7. sourceTextAsyncGeneratorExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncGeneratorFunction.prototype%, sourceText, FormalParameters, AsyncGeneratorBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
  11. 执行 ! DefinePropertyOrThrow(closure, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  12. 执行 ! funcEnv.InitializeBinding(name, closure)。
  13. 返回 closure
注释

AsyncGeneratorExpression 中的 BindingIdentifier 可以从 AsyncGeneratorExpressionAsyncGeneratorBody 内部引用,以允许生成器代码递归调用自身。然而,与 AsyncGeneratorDeclaration 不同,AsyncGeneratorExpression 中的 BindingIdentifier 不能从包围 AsyncGeneratorExpression 的作用域中引用,也不会影响该作用域。

15.6.5 运行时语义:Evaluation

AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody }
  1. 返回 AsyncGeneratorExpressionInstantiateAsyncGeneratorFunctionExpression

15.7 类定义

语法

ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt 注释

类定义始终是 严格模式代码

15.7.1 静态语义:早期错误

ClassTail : ClassHeritageopt { ClassBody } ClassBody : ClassElementList ClassElement : MethodDefinition ClassElement : static MethodDefinition ClassElement : FieldDefinition ; ClassElement : static FieldDefinition ; FieldDefinition : ClassElementName Initializeropt ClassElementName : PrivateIdentifier ClassStaticBlockBody : ClassStaticBlockStatementList

15.7.2 静态语义:ClassElementKind

语法制导操作 ClassElementKind 不接受参数,返回 constructor-methodnon-constructor-methodempty。它按以下产生式分段定义:

ClassElement : MethodDefinition
  1. 如果 MethodDefinitionPropName"constructor",返回 constructor-method
  2. 返回 non-constructor-method
ClassElement : static MethodDefinition FieldDefinition ; static FieldDefinition ;
  1. 返回 non-constructor-method
ClassElement : ClassStaticBlock
  1. 返回 non-constructor-method
ClassElement : ;
  1. 返回 empty

15.7.3 静态语义:ConstructorMethod

语法制导操作 ConstructorMethod 不接受参数,返回一个 ClassElement 解析节点empty。它按以下产生式分段定义:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  2. 返回 empty
ClassElementList : ClassElementList ClassElement
  1. headClassElementListConstructorMethod
  2. 如果 head 不是 empty,返回 head
  3. 如果 ClassElementClassElementKindconstructor-method,返回 ClassElement
  4. 返回 empty
注释

早期错误规则确保只有一个名为 "constructor" 的方法定义,并且它不是 访问器属性 或生成器定义。

15.7.4 静态语义:IsStatic

语法制导操作 IsStatic 不接受参数,返回一个布尔值。它按以下产生式分段定义:

ClassElement : MethodDefinition
  1. 返回 false
ClassElement : static MethodDefinition
  1. 返回 true
ClassElement : FieldDefinition ;
  1. 返回 false
ClassElement : static FieldDefinition ;
  1. 返回 true
ClassElement : ClassStaticBlock
  1. 返回 true
ClassElement : ;
  1. 返回 false

15.7.5 静态语义:NonConstructorElements

语法制导操作 NonConstructorElements 不接受参数,返回一个 List of ClassElement 解析节点。它按以下产生式分段定义:

ClassElementList : ClassElement
  1. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. 返回 « ClassElement »。
  2. 返回一个新的空 List
ClassElementList : ClassElementList ClassElement
  1. listClassElementListNonConstructorElements
  2. 如果 ClassElementClassElementKindnon-constructor-method,则
    1. ClassElement 追加到 list 的末尾。
  3. 返回 list

15.7.6 静态语义:PrototypePropertyNameList

语法制导操作 PrototypePropertyNameList 不接受参数,返回一个 List of 属性键。它按以下产生式分段定义:

ClassElementList : ClassElement
  1. propNameClassElementPropName
  2. 如果 propNameempty,返回一个新的空 List
  3. 如果 ClassElementIsStatictrue,返回一个新的空 List
  4. 返回 « propName »。
ClassElementList : ClassElementList ClassElement
  1. listClassElementListPrototypePropertyNameList
  2. propNameClassElementPropName
  3. 如果 propNameempty,返回 list
  4. 如果 ClassElementIsStatictrue,返回 list
  5. 返回 list 和 « propName » 的 列表连接

15.7.7 静态语义:AllPrivateIdentifiersValid

语法制导操作 AllPrivateIdentifiersValid 接受参数 names(一个 List of Strings),返回一个布尔值。

本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 AllPrivateIdentifiersValid 的默认定义:

  1. 对于此 解析节点 的每个子节点 child,执行
    1. 如果 child 是非终结符的实例,则
      1. 如果 childAllPrivateIdentifiersValid 在参数 names 下是 false,返回 false
  2. 返回 true
MemberExpression : MemberExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 MemberExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
CallExpression : CallExpression . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 CallExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
OptionalChain : ?. PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,返回 true
  2. 返回 false
OptionalChain : OptionalChain . PrivateIdentifier
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 OptionalChainAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false
ClassBody : ClassElementList
  1. newNamesnamesClassBodyPrivateBoundIdentifiers列表连接
  2. 返回 ClassElementListAllPrivateIdentifiersValid 在参数 newNames 下的结果。
RelationalExpression : PrivateIdentifier in ShiftExpression
  1. 如果 names 包含 PrivateIdentifierStringValue,则
    1. 返回 ShiftExpressionAllPrivateIdentifiersValid 在参数 names 下的结果。
  2. 返回 false

15.7.8 静态语义:PrivateBoundIdentifiers

语法制导操作 PrivateBoundIdentifiers 不接受参数,返回一个 List of Strings。它按以下产生式分段定义:

FieldDefinition : ClassElementName Initializeropt
  1. 返回 ClassElementNamePrivateBoundIdentifiers
ClassElementName : PrivateIdentifier
  1. 返回一个 List,其唯一元素是 PrivateIdentifierStringValue
ClassElementName : PropertyName ClassElement : ClassStaticBlock ;
  1. 返回一个新的空 List
ClassElementList : ClassElementList ClassElement
  1. names1ClassElementListPrivateBoundIdentifiers
  2. names2ClassElementPrivateBoundIdentifiers
  3. 返回 names1names2列表连接
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody }
  1. 返回 ClassElementNamePrivateBoundIdentifiers

15.7.9 静态语义:ContainsArguments

语法制导操作 ContainsArguments 不接受参数,返回一个布尔值。

本规范中每个未在下面列出的语法产生式替代都隐含地具有以下 ContainsArguments 的默认定义:

  1. 对于此 解析节点 的每个子节点 child,执行
    1. 如果 child 是非终结符的实例,则
      1. 如果 childContainsArgumentstrue,返回 true
  2. 返回 false
IdentifierReference : Identifier
  1. 如果 IdentifierStringValue"arguments",返回 true
  2. 返回 false
FunctionDeclaration : function BindingIdentifier ( FormalParameters ) { FunctionBody } function ( FormalParameters ) { FunctionBody } FunctionExpression : function BindingIdentifieropt ( FormalParameters ) { FunctionBody } GeneratorDeclaration : function * BindingIdentifier ( FormalParameters ) { GeneratorBody } function * ( FormalParameters ) { GeneratorBody } GeneratorExpression : function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody } AsyncGeneratorDeclaration : async function * BindingIdentifier ( FormalParameters ) { AsyncGeneratorBody } async function * ( FormalParameters ) { AsyncGeneratorBody } AsyncGeneratorExpression : async function * BindingIdentifieropt ( FormalParameters ) { AsyncGeneratorBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 false
MethodDefinition : ClassElementName ( UniqueFormalParameters ) { FunctionBody } get ClassElementName ( ) { FunctionBody } set ClassElementName ( PropertySetParameterList ) { FunctionBody } GeneratorMethod : * ClassElementName ( UniqueFormalParameters ) { GeneratorBody } AsyncGeneratorMethod : async * ClassElementName ( UniqueFormalParameters ) { AsyncGeneratorBody } AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody }
  1. 返回 ClassElementNameContainsArguments

15.7.10 运行时语义:ClassFieldDefinitionEvaluation

语法制导操作 ClassFieldDefinitionEvaluation 接受参数 homeObject(一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition Record 或一个 突然完成。它按以下产生式分段定义:

FieldDefinition : ClassElementName Initializeropt
  1. name 为 ? ClassElementNameEvaluation
  2. 如果 Initializer 存在,则
    1. formalParameterList 为产生式 FormalParameters : [empty] 的一个实例。
    2. env正在运行的执行上下文 的 LexicalEnvironment。
    3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
    4. sourceText 为空的 Unicode 代码点序列。
    5. initializerOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameterList, Initializer, non-lexical-this, env, privateEnv)。
    6. 执行 MakeMethod(initializer, homeObject)。
    7. 设置 initializer.[[ClassFieldInitializerName]]name
  3. 否则,
    1. initializerempty
  4. 返回 ClassFieldDefinition Record { [[Name]]: name, [[Initializer]]: initializer }。
注释
initializer 创建的函数永远不能被 ECMAScript 代码直接访问。

15.7.11 运行时语义:ClassStaticBlockDefinitionEvaluation

语法制导操作 ClassStaticBlockDefinitionEvaluation 接受参数 homeObject(一个 Object),返回一个 ClassStaticBlockDefinition Record。它按以下产生式分段定义:

ClassStaticBlock : static { ClassStaticBlockBody }
  1. lex正在运行的执行上下文 的 LexicalEnvironment。
  2. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  3. sourceText 为空的 Unicode 代码点序列。
  4. formalParameters 为产生式 FormalParameters : [empty] 的一个实例。
  5. bodyFunctionOrdinaryFunctionCreate(%Function.prototype%, sourceText, formalParameters, ClassStaticBlockBody, non-lexical-this, lex, privateEnv)。
  6. 执行 MakeMethod(bodyFunction, homeObject)。
  7. 返回 ClassStaticBlockDefinition Record { [[BodyFunction]]: bodyFunction }。
注释
函数 bodyFunction 永远不能被 ECMAScript 代码直接访问。

15.7.12 运行时语义:EvaluateClassStaticBlockBody

语法制导操作 EvaluateClassStaticBlockBody 接受参数 functionObject(一个 ECMAScript 函数对象),返回一个 返回完成 或一个 抛出完成。它按以下产生式分段定义:

ClassStaticBlockBody : ClassStaticBlockStatementList
  1. 断言functionObject 是由 ClassStaticBlockDefinitionEvaluation 步骤 5 创建的合成函数。
  2. 执行 ! FunctionDeclarationInstantiation(functionObject, « »)。
  3. 执行 ? ClassStaticBlockStatementListEvaluation
  4. 返回 ReturnCompletion(undefined)。

15.7.13 运行时语义:ClassElementEvaluation

语法制导操作 ClassElementEvaluation 接受参数 object(一个 Object),返回一个 正常完成包含 一个 ClassFieldDefinition Record、一个 ClassStaticBlockDefinition Record、一个 PrivateElementunused,或一个 突然完成。它按以下产生式分段定义:

ClassElement : FieldDefinition ; static FieldDefinition ;
  1. 返回 ? FieldDefinitionClassFieldDefinitionEvaluation,参数为 object
ClassElement : MethodDefinition static MethodDefinition
  1. 返回 ? MethodDefinitionMethodDefinitionEvaluation,参数为 objectfalse
ClassElement : ClassStaticBlock
  1. 返回 ClassStaticBlockClassStaticBlockDefinitionEvaluation,参数为 object
ClassElement : ;
  1. 返回 unused

15.7.14 运行时语义:ClassDefinitionEvaluation

语法制导操作 ClassDefinitionEvaluation 接受参数 classBinding(一个 String 或 undefined)和 className(一个 属性键 或一个 Private Name),返回一个 正常完成包含 一个 函数对象 或一个 突然完成

注释

为了便于规范,私有方法和访问器与私有字段一起包含在类实例的 [[PrivateElements]] 槽中。但是,任何给定对象要么拥有给定类定义的所有私有方法和访问器,要么一个都没有。这个特性的设计使得实现可以选择使用不需要单独跟踪每个方法或访问器的策略来实现私有方法和访问器。

例如,实现可以直接将实例私有方法与其相应的 Private Name 关联,并为每个对象跟踪哪些类 构造函数 曾以该对象作为其 this 值运行过。然后在对象上查找实例私有方法就包括检查定义该方法的类 构造函数 是否已被用于初始化该对象,然后返回与 Private Name 关联的方法。

这与私有字段不同:因为字段初始化器可能在类实例化期间抛出异常,单个对象可能拥有给定类的私有字段的某个真子集,因此私有字段通常必须单独跟踪。

它按以下产生式分段定义:

ClassTail : ClassHeritageopt { ClassBodyopt }
  1. env正在运行的执行上下文 的 LexicalEnvironment。
  2. classEnvNewDeclarativeEnvironment(env)。
  3. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.CreateImmutableBinding(classBinding, true)。
  4. outerPrivateEnvironment正在运行的执行上下文 的 PrivateEnvironment。
  5. classPrivateEnvironmentNewPrivateEnvironment(outerPrivateEnvironment)。
  6. 如果 ClassBody 存在,则
    1. 对于 ClassBodyPrivateBoundIdentifiers 中的每个 String dn,执行
      1. 如果 classPrivateEnvironment.[[Names]] 包含一个 Private Name pn 使得 pn.[[Description]]dn,则
        1. 断言:这只可能发生在 getter/setter 对。
      2. 否则,
        1. name 为一个新的 Private Name,其 [[Description]]dn
        2. name 追加到 classPrivateEnvironment.[[Names]]
  7. 如果 ClassHeritage 不存在,则
    1. protoParent%Object.prototype%
    2. constructorParent%Function.prototype%
  8. 否则,
    1. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 classEnv
    2. 注释:当求值 ClassHeritage 时,正在运行的执行上下文 的 PrivateEnvironment 是 outerPrivateEnvironment
    3. superclassRefCompletion(ClassHeritageEvaluation)。
    4. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
    5. superclass 为 ? GetValue(? superclassRef)。
    6. 如果 superclassnull,则
      1. protoParentnull
      2. constructorParent%Function.prototype%
    7. 否则,如果 IsConstructor(superclass) 是 false,则
      1. 抛出 TypeError 异常。
    8. 否则,
      1. protoParent 为 ? Get(superclass, "prototype")。
      2. 如果 protoParent 不是对象protoParent 不是 null,抛出 TypeError 异常。
      3. constructorParentsuperclass
  9. protoOrdinaryObjectCreate(protoParent)。
  10. 如果 ClassBody 不存在,令 constructorempty
  11. 否则,令 constructorClassBodyConstructorMethod
  12. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 classEnv
  13. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 classPrivateEnvironment
  14. 如果 constructorempty,则
    1. defaultConstructor 为一个新的 抽象闭包,不接受参数,不捕获任何值,调用时执行以下步骤:
      1. args 为通过 [[Call]][[Construct]] 传递给此函数的参数 List
      2. 如果 NewTarget 是 undefined,抛出 TypeError 异常。
      3. F活跃函数对象
      4. 如果 F.[[ConstructorKind]]derived,则
        1. 注释:此分支的行为类似于 constructor(...args) { super(...args); }。最显著的区别是,虽然前述 ECMAScript 源文本 会可观察地调用 %Array.prototype% 上的 %Symbol.iterator% 方法,但此函数不会。
        2. func 为 ! F.[[GetPrototypeOf]]()。
        3. 如果 IsConstructor(func) 是 false,抛出 TypeError 异常。
        4. result 为 ? Construct(func, args, NewTarget)。
      5. 否则,
        1. 注释:此分支的行为类似于 constructor() {}
        2. result 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
      6. 执行 ? InitializeInstanceElements(result, F)。
      7. 返回 result
    2. FCreateBuiltinFunction(defaultConstructor, 0, className, « [[ConstructorKind]], [[SourceText]] », 当前 Realm Record, constructorParent)。
  15. 否则,
    1. constructorInfo 为 ! constructorDefineMethod,参数为 protoconstructorParent
    2. FconstructorInfo.[[Closure]]
    3. 执行 MakeClassConstructor(F)。
    4. 执行 SetFunctionName(F, className)。
  16. 执行 MakeConstructor(F, false, proto)。
  17. 如果 ClassHeritage 存在,设置 F.[[ConstructorKind]]derived
  18. 执行 ! DefineMethodProperty(proto, "constructor", F, false)。
  19. 如果 ClassBody 不存在,令 elements 为一个新的空 List
  20. 否则,令 elementsClassBodyNonConstructorElements
  21. instancePrivateMethods 为一个新的空 List
  22. staticPrivateMethods 为一个新的空 List
  23. instanceFields 为一个新的空 List
  24. staticElements 为一个新的空 List
  25. 对于 elements 中的每个 ClassElement e,执行
    1. 如果 eIsStaticfalse,则
      1. elementCompletion(eClassElementEvaluation,参数为 proto)。
    2. 否则,
      1. elementCompletion(eClassElementEvaluation,参数为 F)。
    3. 如果 element 是一个 突然完成,则
      1. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
      2. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
      3. 返回 ? element
    4. 设置 element 为 ! element
    5. 如果 element 是一个 PrivateElement,则
      1. 断言element.[[Kind]]methodaccessor
      2. 如果 eIsStaticfalse,令 containerinstancePrivateMethods
      3. 否则,令 containerstaticPrivateMethods
      4. 如果 container 包含一个 PrivateElement pe 使得 pe.[[Key]]element.[[Key]],则
        1. 断言element.[[Kind]]pe.[[Kind]] 都是 accessor
        2. 如果 element.[[Get]]undefined,则
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: pe.[[Get]], [[Set]]: element.[[Set]] }。
        3. 否则,
          1. combinedPrivateElement { [[Key]]: element.[[Key]], [[Kind]]: accessor, [[Get]]: element.[[Get]], [[Set]]: pe.[[Set]] }。
        4. container 中将 pe 替换为 combined
      5. 否则,
        1. element 追加到 container
    6. 否则,如果 element 是一个 ClassFieldDefinition Record,则
      1. 如果 eIsStaticfalse,将 element 追加到 instanceFields
      2. 否则,将 element 追加到 staticElements
    7. 否则,如果 element 是一个 ClassStaticBlockDefinition Record,则
      1. element 追加到 staticElements
  26. 设置 正在运行的执行上下文 的 LexicalEnvironment 为 env
  27. 如果 classBinding 不是 undefined,则
    1. 执行 ! classEnv.InitializeBinding(classBinding, F)。
  28. 设置 F.[[PrivateMethods]]instancePrivateMethods
  29. 设置 F.[[Fields]]instanceFields
  30. 对于 staticPrivateMethods 中的每个 PrivateElement method,执行
    1. 执行 ! PrivateMethodOrAccessorAdd(F, method)。
  31. 对于 staticElements 中的每个元素 elementRecord,执行
    1. 如果 elementRecord 是一个 ClassFieldDefinition Record,则
      1. resultCompletion(DefineField(F, elementRecord))。
    2. 否则,
      1. 断言elementRecord 是一个 ClassStaticBlockDefinition Record
      2. resultCompletion(Call(elementRecord.[[BodyFunction]], F))。
    3. 如果 result 是一个 突然完成,则
      1. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
      2. 返回 ? result
  32. 设置 正在运行的执行上下文 的 PrivateEnvironment 为 outerPrivateEnvironment
  33. 返回 F

15.7.15 运行时语义:BindingClassDeclarationEvaluation

语法制导操作 BindingClassDeclarationEvaluation 不接受参数,返回一个 正常完成包含 一个 函数对象 或一个 突然完成。它按以下产生式分段定义:

ClassDeclaration : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. value 为 ? ClassTailClassDefinitionEvaluation,参数为 classNameclassName
  3. 设置 value.[[SourceText]]ClassDeclaration 匹配的源文本
  4. env正在运行的执行上下文 的 LexicalEnvironment。
  5. 执行 ? InitializeBoundName(className, value, env)。
  6. 返回 value
ClassDeclaration : class ClassTail
  1. value 为 ? ClassTailClassDefinitionEvaluation,参数为 undefined"default"
  2. 设置 value.[[SourceText]]ClassDeclaration 匹配的源文本
  3. 返回 value
注释

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,其绑定的建立作为该产生式的求值操作的一部分处理。参见 16.2.3.7

15.7.16 运行时语义:Evaluation

ClassDeclaration : class BindingIdentifier ClassTail
  1. 执行 ? 此 ClassDeclarationBindingClassDeclarationEvaluation
  2. 返回 empty
注释

ClassDeclaration : class ClassTail 只作为 ExportDeclaration 的一部分出现,从不直接求值。

ClassExpression : class ClassTail
  1. value 为 ? ClassTailClassDefinitionEvaluation,参数为 undefined""
  2. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  3. 返回 value
ClassExpression : class BindingIdentifier ClassTail
  1. classNameBindingIdentifierStringValue
  2. value 为 ? ClassTailClassDefinitionEvaluation,参数为 classNameclassName
  3. 设置 value.[[SourceText]]ClassExpression 匹配的源文本
  4. 返回 value
ClassElementName : PrivateIdentifier
  1. privateIdentifierPrivateIdentifierStringValue
  2. privateEnvRec正在运行的执行上下文 的 PrivateEnvironment。
  3. namesprivateEnvRec.[[Names]]
  4. 断言names 中恰好有一个元素是 Private Name,其 [[Description]]privateIdentifier
  5. privateNamenames[[Description]]privateIdentifierPrivate Name
  6. 返回 privateName
ClassStaticBlockStatementList : [empty]
  1. 返回 undefined

15.8 异步函数定义

语法

AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] 注释 1

当存在 [Await] 参数时,await 被解析为 AwaitExpression关键字[Await] 参数在以下上下文的顶层存在,尽管根据非终结符(如 FunctionBody),在某些上下文中该参数可能不存在:

Script 是语法目标符号时,当不存在 [Await] 参数时,await 可能被解析为标识符。这包括以下上下文:

注释 2

YieldExpression 不同,省略 AwaitExpression 的操作数是语法错误。你必须等待某些东西。

15.8.1 静态语义:早期错误

AsyncMethod : async ClassElementName ( UniqueFormalParameters ) { AsyncFunctionBody } AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody } async function ( FormalParameters ) { AsyncFunctionBody } AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }

15.8.2 运行时语义:InstantiateAsyncFunctionObject

语法制导操作 InstantiateAsyncFunctionObject 接受参数 env(一个 Environment Record)和 privateEnv(一个 PrivateEnvironment Recordnull),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncFunctionDeclaration : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. nameBindingIdentifierStringValue
  2. sourceTextAsyncFunctionDeclaration 匹配的源文本
  3. FOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  4. 执行 SetFunctionName(F, name)。
  5. 返回 F
AsyncFunctionDeclaration : async function ( FormalParameters ) { AsyncFunctionBody }
  1. sourceTextAsyncFunctionDeclaration 匹配的源文本
  2. FOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  3. 执行 SetFunctionName(F, "default")。
  4. 返回 F

15.8.3 运行时语义:InstantiateAsyncFunctionExpression

语法制导操作 InstantiateAsyncFunctionExpression 接受可选参数 name(一个 属性键 或一个 Private Name),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncFunctionExpression : async function ( FormalParameters ) { AsyncFunctionBody }
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncFunctionExpression 匹配的源文本
  5. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, env, privateEnv)。
  6. 执行 SetFunctionName(closure, name)。
  7. 返回 closure
AsyncFunctionExpression : async function BindingIdentifier ( FormalParameters ) { AsyncFunctionBody }
  1. 断言name 不存在。
  2. 设置 nameBindingIdentifierStringValue
  3. outerEnv正在运行的执行上下文 的 LexicalEnvironment。
  4. funcEnvNewDeclarativeEnvironment(outerEnv)。
  5. 执行 ! funcEnv.CreateImmutableBinding(name, false)。
  6. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  7. sourceTextAsyncFunctionExpression 匹配的源文本
  8. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, FormalParameters, AsyncFunctionBody, non-lexical-this, funcEnv, privateEnv)。
  9. 执行 SetFunctionName(closure, name)。
  10. 执行 ! funcEnv.InitializeBinding(name, closure)。
  11. 返回 closure
注释

AsyncFunctionExpression 中的 BindingIdentifier 可以从 AsyncFunctionExpressionAsyncFunctionBody 内部引用,以允许函数递归调用自身。但是,与 FunctionDeclaration 不同,AsyncFunctionExpression 中的 BindingIdentifier 不能从包围 AsyncFunctionExpression 的作用域中引用,也不影响该作用域。

15.8.4 运行时语义:EvaluateAsyncFunctionBody

语法制导操作 EvaluateAsyncFunctionBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),返回一个 返回完成。它按以下产生式分段定义:

AsyncFunctionBody : FunctionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是一个 突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, FunctionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.8.5 运行时语义:Evaluation

AsyncFunctionExpression : async function BindingIdentifieropt ( FormalParameters ) { AsyncFunctionBody }
  1. 返回 AsyncFunctionExpressionInstantiateAsyncFunctionExpression
AwaitExpression : await UnaryExpression
  1. exprRef 为 ? UnaryExpressionEvaluation
  2. value 为 ? GetValue(exprRef)。
  3. 返回 ? Await(value)。

15.9 异步箭头函数定义

语法

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

补充语法

当处理产生式实例
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
时,使用以下语法来细化对 CoverCallExpressionAndAsyncArrowHead 的解释:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

15.9.1 静态语义:早期错误

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody

15.9.2 静态语义:AsyncConciseBodyContainsUseStrict

语法制导操作 AsyncConciseBodyContainsUseStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:

AsyncConciseBody : ExpressionBody
  1. 返回 false
AsyncConciseBody : { AsyncFunctionBody }
  1. 返回 AsyncFunctionBodyFunctionBodyContainsUseStrict

15.9.3 运行时语义:EvaluateAsyncConciseBody

语法制导操作 EvaluateAsyncConciseBody 接受参数 functionObject(一个 ECMAScript 函数对象)和 argumentsList(一个 List of ECMAScript 语言值),返回一个 返回完成。它按以下产生式分段定义:

AsyncConciseBody : ExpressionBody
  1. promiseCapability 为 ! NewPromiseCapability(%Promise%)。
  2. completionCompletion(FunctionDeclarationInstantiation(functionObject, argumentsList))。
  3. 如果 completion 是一个 突然完成,则
    1. 执行 ! Call(promiseCapability.[[Reject]], undefined, « completion.[[Value]] »)。
  4. 否则,
    1. 执行 AsyncFunctionStart(promiseCapability, ExpressionBody)。
  5. 返回 ReturnCompletion(promiseCapability.[[Promise]])。

15.9.4 运行时语义:InstantiateAsyncArrowFunctionExpression

语法制导操作 InstantiateAsyncArrowFunctionExpression 接受可选参数 name(一个 属性键 或一个 Private Name),返回一个 ECMAScript 函数对象。它按以下产生式分段定义:

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction 匹配的源文本
  5. parametersAsyncArrowBindingIdentifier
  6. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  7. 执行 SetFunctionName(closure, name)。
  8. 返回 closure
AsyncArrowFunction : CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 如果 name 不存在,设置 name""
  2. env正在运行的执行上下文 的 LexicalEnvironment。
  3. privateEnv正在运行的执行上下文 的 PrivateEnvironment。
  4. sourceTextAsyncArrowFunction 匹配的源文本
  5. head 为被 CoverCallExpressionAndAsyncArrowHead 覆盖AsyncArrowHead
  6. parametersheadArrowFormalParameters
  7. closureOrdinaryFunctionCreate(%AsyncFunction.prototype%, sourceText, parameters, AsyncConciseBody, lexical-this, env, privateEnv)。
  8. 执行 SetFunctionName(closure, name)。
  9. 返回 closure

15.9.5 运行时语义:Evaluation

AsyncArrowFunction : async AsyncArrowBindingIdentifier => AsyncConciseBody CoverCallExpressionAndAsyncArrowHead => AsyncConciseBody
  1. 返回 AsyncArrowFunctionInstantiateAsyncArrowFunctionExpression

15.10 尾位置调用

15.10.1 静态语义:IsInTailPosition ( call )

抽象操作 IsInTailPosition 接受参数 call(一个 CallExpression 解析节点、一个 MemberExpression 解析节点,或一个 OptionalChain 解析节点),返回一个 Boolean。调用时执行以下步骤:

  1. 如果 IsStrict(call) 是 false,返回 false
  2. 如果 call 不包含在 FunctionBodyConciseBodyAsyncConciseBody 中,返回 false
  3. body 为最紧密包含 callFunctionBodyConciseBodyAsyncConciseBody
  4. 如果 bodyGeneratorBodyFunctionBody,返回 false
  5. 如果 bodyAsyncFunctionBodyFunctionBody,返回 false
  6. 如果 bodyAsyncGeneratorBodyFunctionBody,返回 false
  7. 如果 bodyAsyncConciseBody,返回 false
  8. 返回 body 以参数 call 进行的 HasCallInTailPosition 的结果。
注释

尾位置调用仅在 严格模式代码 中定义,因为有一个常见的非标准语言扩展(参见 10.2.4)可以观察调用者上下文链。

15.10.2 静态语义:HasCallInTailPosition

语法制导操作 HasCallInTailPosition 接受参数 call(一个 CallExpression 解析节点、一个 MemberExpression 解析节点,或一个 OptionalChain 解析节点),返回一个 Boolean。

注释 1

call 是一个 解析节点,表示特定范围的源文本。当以下算法将 call 与另一个 解析节点 进行比较时,这是测试它们是否表示相同的源文本。

注释 2

紧接着返回调用结果的 GetValue 的潜在尾位置调用也是可能的尾位置调用。函数调用不能返回 Reference Record,因此这样的 GetValue 操作将总是返回与实际函数调用结果相同的值。

它按以下产生式分段定义:

StatementList : StatementList StatementListItem
  1. hasStatementList 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回 StatementListItem 以参数 call 进行的 HasCallInTailPosition
FunctionStatementList : [empty] StatementListItem : Declaration Statement : VariableStatement EmptyStatement ExpressionStatement ContinueStatement BreakStatement ThrowStatement DebuggerStatement Block : { } ReturnStatement : return ; LabelledItem : FunctionDeclaration ForInOfStatement : for ( LeftHandSideExpression of AssignmentExpression ) Statement for ( var ForBinding of AssignmentExpression ) Statement for ( ForDeclaration of AssignmentExpression ) Statement CaseBlock : { }
  1. 返回 false
IfStatement : if ( Expression ) Statement else Statement
  1. has 为第一个 Statement 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回第二个 Statement 以参数 call 进行的 HasCallInTailPosition
IfStatement : if ( Expression ) Statement DoWhileStatement : do Statement while ( Expression ) ; WhileStatement : while ( Expression ) Statement ForStatement : for ( Expressionopt ; Expressionopt ; Expressionopt ) Statement for ( var VariableDeclarationList ; Expressionopt ; Expressionopt ) Statement for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement ForInOfStatement : for ( LeftHandSideExpression in Expression ) Statement for ( var ForBinding in Expression ) Statement for ( ForDeclaration in Expression ) Statement WithStatement : with ( Expression ) Statement
  1. 返回 Statement 以参数 call 进行的 HasCallInTailPosition
LabelledStatement : LabelIdentifier : LabelledItem
  1. 返回 LabelledItem 以参数 call 进行的 HasCallInTailPosition
ReturnStatement : return Expression ;
  1. 返回 Expression 以参数 call 进行的 HasCallInTailPosition
SwitchStatement : switch ( Expression ) CaseBlock
  1. 返回 CaseBlock 以参数 call 进行的 HasCallInTailPosition
CaseBlock : { CaseClausesopt DefaultClause CaseClausesopt }
  1. hasfalse
  2. 如果存在第一个 CaseClauses,将 has 设置为第一个 CaseClauses 以参数 call 进行的 HasCallInTailPosition
  3. 如果 hastrue,返回 true
  4. has 设置为 DefaultClause 以参数 call 进行的 HasCallInTailPosition
  5. 如果 hastrue,返回 true
  6. 如果存在第二个 CaseClauses,将 has 设置为第二个 CaseClauses 以参数 call 进行的 HasCallInTailPosition
  7. 返回 has
CaseClauses : CaseClauses CaseClause
  1. hasCaseClauses 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回 CaseClause 以参数 call 进行的 HasCallInTailPosition
CaseClause : case Expression : StatementListopt DefaultClause : default : StatementListopt
  1. 如果存在 StatementList,返回 StatementList 以参数 call 进行的 HasCallInTailPosition
  2. 返回 false
TryStatement : try Block Catch
  1. 返回 Catch 以参数 call 进行的 HasCallInTailPosition
TryStatement : try Block Finally try Block Catch Finally
  1. 返回 Finally 以参数 call 进行的 HasCallInTailPosition
Catch : catch ( CatchParameter ) Block
  1. 返回 Block 以参数 call 进行的 HasCallInTailPosition
AssignmentExpression : YieldExpression ArrowFunction AsyncArrowFunction LeftHandSideExpression = AssignmentExpression LeftHandSideExpression AssignmentOperator AssignmentExpression LeftHandSideExpression &&= AssignmentExpression LeftHandSideExpression ||= AssignmentExpression LeftHandSideExpression ??= AssignmentExpression BitwiseANDExpression : BitwiseANDExpression & EqualityExpression BitwiseXORExpression : BitwiseXORExpression ^ BitwiseANDExpression BitwiseORExpression : BitwiseORExpression | BitwiseXORExpression EqualityExpression : EqualityExpression == RelationalExpression EqualityExpression != RelationalExpression EqualityExpression === RelationalExpression EqualityExpression !== RelationalExpression RelationalExpression : RelationalExpression < ShiftExpression RelationalExpression > ShiftExpression RelationalExpression <= ShiftExpression RelationalExpression >= ShiftExpression RelationalExpression instanceof ShiftExpression RelationalExpression in ShiftExpression PrivateIdentifier in ShiftExpression ShiftExpression : ShiftExpression << AdditiveExpression ShiftExpression >> AdditiveExpression ShiftExpression >>> AdditiveExpression AdditiveExpression : AdditiveExpression + MultiplicativeExpression AdditiveExpression - MultiplicativeExpression MultiplicativeExpression : MultiplicativeExpression MultiplicativeOperator ExponentiationExpression ExponentiationExpression : UpdateExpression ** ExponentiationExpression UpdateExpression : LeftHandSideExpression ++ LeftHandSideExpression -- ++ UnaryExpression -- UnaryExpression UnaryExpression : delete UnaryExpression void UnaryExpression typeof UnaryExpression + UnaryExpression - UnaryExpression ~ UnaryExpression ! UnaryExpression AwaitExpression CallExpression : SuperCall ImportCall CallExpression [ Expression ] CallExpression . IdentifierName CallExpression . PrivateIdentifier NewExpression : new NewExpression MemberExpression : MemberExpression [ Expression ] MemberExpression . IdentifierName SuperProperty MetaProperty new MemberExpression Arguments MemberExpression . PrivateIdentifier PrimaryExpression : this IdentifierReference Literal ArrayLiteral ObjectLiteral FunctionExpression ClassExpression GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral
  1. 返回 false
Expression : AssignmentExpression Expression , AssignmentExpression
  1. 返回 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
ConditionalExpression : ShortCircuitExpression ? AssignmentExpression : AssignmentExpression
  1. has 为第一个 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
  2. 如果 hastrue,返回 true
  3. 返回第二个 AssignmentExpression 以参数 call 进行的 HasCallInTailPosition
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
  1. 返回 BitwiseORExpression 以参数 call 进行的 HasCallInTailPosition
LogicalORExpression : LogicalORExpression || LogicalANDExpression
  1. 返回 LogicalANDExpression 以参数 call 进行的 HasCallInTailPosition
CoalesceExpression : CoalesceExpressionHead ?? BitwiseORExpression
  1. 返回 BitwiseORExpression 以参数 call 进行的 HasCallInTailPosition
CallExpression : CoverCallExpressionAndAsyncArrowHead CallExpression Arguments CallExpression TemplateLiteral
  1. 如果此 CallExpressioncall,返回 true
  2. 返回 false
OptionalExpression : MemberExpression OptionalChain CallExpression OptionalChain OptionalExpression OptionalChain
  1. 返回 OptionalChain 以参数 call 进行的 HasCallInTailPosition
OptionalChain : ?. [ Expression ] ?. IdentifierName ?. PrivateIdentifier OptionalChain [ Expression ] OptionalChain . IdentifierName OptionalChain . PrivateIdentifier
  1. 返回 false
OptionalChain : ?. Arguments OptionalChain Arguments
  1. 如果此 OptionalChaincall,返回 true
  2. 返回 false
MemberExpression : MemberExpression TemplateLiteral
  1. 如果此 MemberExpressioncall,返回 true
  2. 返回 false
PrimaryExpression : CoverParenthesizedExpressionAndArrowParameterList
  1. expr 为被 CoverParenthesizedExpressionAndArrowParameterList 覆盖ParenthesizedExpression
  2. 返回 expr 以参数 call 进行的 HasCallInTailPosition
ParenthesizedExpression : ( Expression )
  1. 返回 Expression 以参数 call 进行的 HasCallInTailPosition

15.10.3 PrepareForTailCall ( )

抽象操作 PrepareForTailCall 不接受参数,返回 unused。调用时执行以下步骤:

  1. 断言:当前 执行上下文 随后不会用于任何 ECMAScript 代码或内置函数的求值。在调用此抽象操作之后对 Call 的调用将在执行任何此类求值之前创建并推入一个新的 执行上下文
  2. 丢弃与当前 执行上下文 关联的所有资源。
  3. 返回 unused

尾位置调用必须在调用目标函数之前释放与当前执行函数 执行上下文 关联的任何瞬态内部资源,或重用这些资源来支持目标函数。

注释

例如,尾位置调用应该仅按目标函数的激活记录大小超出调用函数激活记录大小的量来增长实现的激活记录栈。如果目标函数的激活记录更小,则栈的总大小应该减少。

16 ECMAScript 语言:脚本和模块

16.1 脚本

语法

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return]

16.1.1 静态语义:早期错误

Script : ScriptBody ScriptBody : StatementList

16.1.2 静态语义:ScriptIsStrict

语法制导操作 ScriptIsStrict 不接受参数,返回一个 Boolean。它按以下产生式分段定义:

Script : ScriptBodyopt
  1. 如果 ScriptBody 存在且 ScriptBody指令序言 包含一个 Use Strict 指令,返回 true;否则,返回 false

16.1.3 运行时语义:Evaluation

Script : [empty]
  1. 返回 undefined

16.1.4 脚本记录

脚本记录 封装了关于被求值脚本的信息。每个脚本记录包含 表 39 中列出的字段。

表 39:脚本记录 字段
字段名 值类型 含义
[[Realm]] 一个 Realm Record 创建此脚本的 realm
[[ECMAScriptCode]] 一个 Script 解析节点 解析此脚本源文本的结果。
[[LoadedModules]] 一个 LoadedModuleRequest RecordsList 从此脚本导入的说明符字符串到已解析的 Module Record 的映射。该列表不包含两个不同的 Records r1r2,使得 ModuleRequestsEqual(r1, r2) 是 true
[[HostDefined]] 任何东西(默认值是 empty 为需要将附加信息与脚本关联的 宿主环境 预留的字段。

16.1.5 ParseScript ( sourceText, realm, hostDefined )

抽象操作 ParseScript 接受参数 sourceTextECMAScript 源文本)、realm(一个 Realm Record)和 hostDefined(任何东西),返回一个 脚本记录 或一个非空的 SyntaxError 对象 List。它基于将 sourceText 解析为 Script 的结果创建一个 脚本记录。调用时执行以下步骤:

  1. scriptParseText(sourceText, Script)。
  2. 如果 script 是一个错误的 List,返回 script
  3. 返回 脚本记录 { [[Realm]]: realm, [[ECMAScriptCode]]: script, [[LoadedModules]]: « », [[HostDefined]]: hostDefined }。
注释

实现可以在对该脚本源文本执行 ParseScript 之前解析脚本源文本并分析其早期错误条件。但是,任何错误的报告必须推迟到本规范实际对该源文本执行 ParseScript 的时候。

16.1.6 ScriptEvaluation ( scriptRecord )

抽象操作 ScriptEvaluation 接受参数 scriptRecord(一个 脚本记录),返回包含一个 ECMAScript 语言值正常完成 或一个 突然完成。调用时执行以下步骤:

  1. globalEnvscriptRecord.[[Realm]].[[GlobalEnv]]
  2. scriptContext 为一个新的 ECMAScript 代码执行上下文
  3. 设置 scriptContext 的 Function 为 null
  4. 设置 scriptContextRealmscriptRecord.[[Realm]]
  5. 设置 scriptContext 的 ScriptOrModule 为 scriptRecord
  6. 设置 scriptContext 的 VariableEnvironment 为 globalEnv
  7. 设置 scriptContext 的 LexicalEnvironment 为 globalEnv
  8. 设置 scriptContext 的 PrivateEnvironment 为 null
  9. 挂起 正在运行的执行上下文
  10. scriptContext 推入 执行上下文栈scriptContext 现在是 正在运行的执行上下文
  11. scriptscriptRecord.[[ECMAScriptCode]]
  12. resultCompletion(GlobalDeclarationInstantiation(script, globalEnv))。
  13. 如果 result 是一个 正常完成,则
    1. 设置 resultCompletion(scriptEvaluation)。
    2. 如果 result 是一个 正常完成result.[[Value]]empty,则
      1. 设置 resultNormalCompletion(undefined)。
  14. 挂起 scriptContext 并将其从 执行上下文栈 中移除。
  15. 断言执行上下文栈 不为空。
  16. 恢复现在位于 执行上下文栈 顶部的上下文作为 正在运行的执行上下文
  17. 返回 ? result

16.1.7 GlobalDeclarationInstantiation ( script, env )

抽象操作 GlobalDeclarationInstantiation 接受参数 script(一个 Script 解析节点)和 env(一个 全局环境记录),返回包含 unused正常完成 或一个 抛出完成script 是正在为其建立 执行上下文Scriptenv 是要在其中创建绑定的全局环境。

注释 1

当为求值脚本建立 执行上下文 时,声明在当前全局环境中实例化。代码中声明的每个全局绑定都被实例化。

调用时执行以下步骤:

  1. lexNamesscriptLexicallyDeclaredNames
  2. varNamesscriptVarDeclaredNames
  3. 对于 lexNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 是 true,抛出一个 SyntaxError 异常。
    2. hasRestrictedGlobal 为 ? HasRestrictedGlobalProperty(env, name)。
    3. 注释:全局 varfunction 绑定(除了由非严格 直接 eval 引入的那些)是不可配置的,因此是受限制的全局属性。
    4. 如果 hasRestrictedGlobaltrue,抛出一个 SyntaxError 异常。
  4. 对于 varNames 的每个元素 name,执行
    1. 如果 HasLexicalDeclaration(env, name) 是 true,抛出一个 SyntaxError 异常。
  5. varDeclarationsscriptVarScopedDeclarations
  6. functionsToInitialize 为一个新的空 List
  7. declaredFunctionNames 为一个新的空 List
  8. 对于 varDeclarations 的每个元素 d,按反向 List 顺序,执行
    1. 如果 d 不是 VariableDeclarationForBindingBindingIdentifier,则
      1. 断言dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注释:如果同一个名称有多个函数声明,使用最后的声明。
      3. fndBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,则
        1. fnDefinable 为 ? CanDeclareGlobalFunction(env, fn)。
        2. 如果 fnDefinablefalse,抛出一个 TypeError 异常。
        3. fn 追加到 declaredFunctionNames
        4. d 作为 functionsToInitialize 的第一个元素插入。
  9. declaredVarNames 为一个新的空 List
  10. 对于 varDeclarations 的每个元素 d,执行
    1. 如果 dVariableDeclarationForBindingBindingIdentifier,则
      1. 对于 dBoundNames 的每个字符串 vn,执行
        1. 如果 declaredFunctionNames 不包含 vn,则
          1. vnDefinable 为 ? CanDeclareGlobalVar(env, vn)。
          2. 如果 vnDefinablefalse,抛出一个 TypeError 异常。
          3. 如果 declaredVarNames 不包含 vn,则
            1. vn 追加到 declaredVarNames
  11. 注释:如果 全局对象 是一个 普通对象,则在此算法步骤之后不会发生异常终止。但是,如果 全局对象 是一个 Proxy 异质对象,它可能表现出在以下某些步骤中导致异常终止的行为。
  12. 注释:附录 B.3.2.2 在此处添加了附加步骤。
  13. lexDeclarationsscriptLexicallyScopedDeclarations
  14. privateEnvnull
  15. 对于 lexDeclarations 的每个元素 d,执行
    1. 注释:词法声明的名称仅在此处实例化但不初始化。
    2. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,则
        1. 执行 ? env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? env.CreateMutableBinding(dn, false)。
  16. 对于 functionsToInitialize 的每个 解析节点 f,执行
    1. fnfBoundNames 的唯一元素。
    2. fof 以参数 envprivateEnv 进行的 InstantiateFunctionObject
    3. 执行 ? CreateGlobalFunctionBinding(env, fn, fo, false)。
  17. 对于 declaredVarNames 的每个字符串 vn,执行
    1. 执行 ? CreateGlobalVarBinding(env, vn, false)。
  18. 返回 unused
注释 2

16.1.1 中指定的 早期错误 防止了函数/var 声明与 let/const/class 声明之间的名称冲突,以及单个 Script 内包含的声明的 let/const/class 绑定的重新声明。但是,这种跨越多个 Script 的冲突和重新声明在 GlobalDeclarationInstantiation 期间被检测为运行时错误。如果检测到任何此类错误,则不会为脚本实例化绑定。但是,如果 全局对象 使用 Proxy 异质对象 定义,则冲突声明的运行时测试可能不可靠,导致 突然完成 和一些全局声明未被实例化。如果发生这种情况,Script 的代码不会被求值。

与显式的 var 或 function 声明不同,直接在 全局对象 上创建的属性会导致可能被 let/const/class 声明遮蔽的全局绑定。

16.2 模块

语法

Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral

16.2.1 模块语义

16.2.1.1 静态语义:早期错误

ModuleBody : ModuleItemList

重复 ExportedNames 规则 意味着在 ModuleBody 中包含多个 export default ExportDeclaration 项是语法错误。在 Module 求值之前的模块链接期间检查与冲突或重复声明相关的其他错误条件。如果检测到任何此类错误,则不会对 Module 进行求值。

ModuleExportName : StringLiteral

16.2.1.2 静态语义:ImportedLocalNames ( importEntries )

抽象操作 ImportedLocalNames 接受参数 importEntries(一个 List of ImportEntry Records)并返回一个字符串的 List。它创建一个包含所有由 importEntries 定义的本地名称绑定的 List。调用时它执行以下步骤:

  1. localNames 为一个新的空 List
  2. 对于 importEntries 的每个 ImportEntry Record i,执行
    1. i.[[LocalName]] 追加到 localNames
  3. 返回 localNames

16.2.1.3 ModuleRequest 记录

ModuleRequest Record 表示带有给定导入属性的模块导入请求。它由以下字段组成:

表 40:ModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] 一个字符串 模块说明符
[[Attributes]] 一个 List of ImportAttribute Records 导入属性

LoadedModuleRequest Record 表示模块导入请求以及结果 Module Record。它由表 表 40 中定义的相同字段组成,并添加了 [[Module]]

表 41:LoadedModuleRequest Record 字段
字段名称 值类型 含义
[[Specifier]] 一个字符串 模块说明符
[[Attributes]] 一个 List of ImportAttribute Records 导入属性
[[Module]] 一个 Module Record 与此模块请求对应的已加载模块

ImportAttribute Record 由以下字段组成:

表 42:ImportAttribute Record 字段
字段名称 值类型 含义
[[Key]] 一个字符串 属性键
[[Value]] 一个字符串 属性值

16.2.1.3.1 ModuleRequestsEqual ( left, right )

抽象操作 ModuleRequestsEqual 接受参数 left(一个 ModuleRequest Record 或一个 LoadedModuleRequest Record) 和 right(一个 ModuleRequest Record 或一个 LoadedModuleRequest Record) 并返回一个布尔值。调用时它执行以下步骤:

  1. 如果 left.[[Specifier]] 不是 right.[[Specifier]],返回 false
  2. leftAttrsleft.[[Attributes]]
  3. rightAttrsright.[[Attributes]]
  4. leftAttrsCountleftAttrs 中元素的数量。
  5. rightAttrsCountrightAttrs 中元素的数量。
  6. 如果 leftAttrsCountrightAttrsCount,返回 false
  7. 对于 leftAttrs 的每个 ImportAttribute Record l,执行
    1. 如果 rightAttrs 不包含一个 ImportAttribute Record r 使得 l.[[Key]]r.[[Key]]l.[[Value]]r.[[Value]],返回 false
  8. 返回 true

16.2.1.4 静态语义:ModuleRequests

语法导向操作 ModuleRequests 不接受参数并返回一个 List of ModuleRequest Records。它对以下产生式逐段定义:

Module : [empty]
  1. 返回一个新的空 List
ModuleItemList : ModuleItem
  1. 返回 ModuleItemModuleRequests
ModuleItemList : ModuleItemList ModuleItem
  1. requestsModuleItemListModuleRequests
  2. additionalRequestsModuleItemModuleRequests
  3. 对于 additionalRequests 的每个 ModuleRequest Record mr,执行
    1. 如果 requests 不包含一个 ModuleRequest Record mr2 使得 ModuleRequestsEqual(mr, mr2) 是 true,那么
      1. mr 追加到 requests
  4. 返回 requests
ModuleItem : StatementListItem
  1. 返回一个新的空 List
ImportDeclaration : import ImportClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ImportClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ImportDeclaration : import ModuleSpecifier ;
  1. specifierModuleSpecifierSV
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ImportDeclaration : import ModuleSpecifier WithClause ;
  1. specifierModuleSpecifierSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ExportDeclaration : export ExportFromClause FromClause ;
  1. specifierFromClauseSV
  2. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: « » }。
ExportDeclaration : export ExportFromClause FromClause WithClause ;
  1. specifierFromClauseSV
  2. attributesWithClauseWithClauseToAttributes
  3. 返回一个 List,其唯一元素是 ModuleRequest Record { [[Specifier]]: specifier, [[Attributes]]: attributes }。
ExportDeclaration : export NamedExports ; export VariableStatement export Declaration export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回一个新的空 List

16.2.1.5 抽象模块记录

Module Record 封装了单个模块的导入和导出的结构信息。此信息用于链接连接模块集合的导入和导出。Module Record 包含四个仅在求值模块时使用的字段。

出于规范目的,Module Record 值是 Record 规范类型的值,可以认为存在于一个简单的面向对象层次结构中,其中 Module Record 是一个抽象类,具有抽象和具体子类。本规范定义了名为 Cyclic Module Record 的抽象子类及其名为 Source Text Module Record 的具体子类。其他规范和实现可以定义对应于它们定义的替代模块定义设施的额外 Module Record 子类。

Module Record 定义了 表 43 中列出的字段。所有 Module Definition 子类至少包含这些字段。Module Record 还定义了 表 44 中的抽象方法列表。所有 Module definition 子类必须提供这些抽象方法的具体实现。

表 43:Module Record 字段
字段名称 值类型 含义
[[Realm]] 一个 Realm Record 创建此模块的 Realm
[[Environment]] 一个 Module Environment Recordempty 包含此模块顶级绑定的 Environment Record。此字段在模块链接时设置。
[[Namespace]] 一个对象或 empty 如果为此模块创建了模块命名空间对象(28.3)。
[[HostDefined]] 任何内容(默认值为 undefined 为需要将附加信息与模块关联的 宿主环境 保留的字段。
表 44:Module Records 的抽象方法
方法 目的
LoadRequestedModules([hostDefined])

通过递归加载所有依赖项为链接准备模块,并返回一个 promise。

GetExportedNames([exportStarSet])

返回从此模块直接或间接导出的所有名称的列表。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

ResolveExport(exportName [, resolveSet])

返回此模块导出的名称的绑定。绑定由 ResolvedBinding Record 表示,形式为 { [[Module]]: Module Record, [[BindingName]]: String | namespace }。如果导出是没有任何模块中直接绑定的模块命名空间对象,[[BindingName]] 将设置为 namespace。如果名称无法解析,返回 null,如果找到多个绑定,返回 ambiguous

每次使用特定的 exportNameresolveSet 对作为参数调用此操作时,必须返回相同的结果。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Link()

通过传递性地解析所有模块依赖项并创建 Module Environment Record 为求值准备模块。

在调用此方法之前,LoadRequestedModules 必须已成功完成。

Evaluate()

返回用于此模块及其依赖项求值的 promise,在成功求值或已成功求值时解析,在求值错误或已求值失败时拒绝。如果 promise 被拒绝,期望 宿主 处理 promise 拒绝并重新抛出求值错误。

在调用此方法之前,Link 必须已成功完成。

16.2.1.5.1 EvaluateModuleSync ( module )

抽象操作 EvaluateModuleSync 接受参数 module(一个 Module Record)并返回 一个 正常完成,包含 unused 或一个 抛出完成。它同步求值 module,前提是调用者保证 module 的求值将返回一个已经结算的 promise。调用时它执行以下步骤:

  1. 断言module 不是 Cyclic Module Record
  2. promisemodule.Evaluate()。
  3. 断言promise.[[PromiseState]]fulfilledrejected
  4. 如果 promise.[[PromiseState]]rejected,那么
    1. 如果 promise.[[PromiseIsHandled]]false,执行 HostPromiseRejectionTracker(promise, "handle")。
    2. 设置 promise.[[PromiseIsHandled]]true
    3. 返回 ThrowCompletion(promise.[[PromiseResult]])。
  5. 返回 unused

16.2.1.6 循环模块记录

Cyclic Module Record 用于表示可以与 Cyclic Module Record 类型的子类的其他模块参与依赖循环的模块的信息。不是 Cyclic Module Record 类型的子类的 Module Records 不得与 Source Text Module Records 参与依赖循环。

除了 表 43 中定义的字段外,Cyclic Module Records 还具有 表 45 中列出的附加字段

表 45:Cyclic Module Records 的附加字段
字段名称 值类型 含义
[[Status]] newunlinkedlinkinglinkedevaluatingevaluating-asyncevaluated 初始为 new。随着模块在其生命周期中的进展,按顺序转换为 unlinkedlinkinglinkedevaluating、 可能是 evaluating-asyncevaluatedevaluating-async 表示此模块排队等待在其异步依赖完成时执行,或者它是一个 [[HasTLA]] 字段为 true 的模块,已执行并等待顶级完成。
[[EvaluationError]] 一个 抛出完成empty 表示求值期间发生的异常的 抛出完成。如果没有发生异常或 [[Status]] 不是 evaluated,则为 undefined
[[DFSIndex]] 一个 整数empty 仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating, 此非负数记录模块在依赖图的深度优先遍历中首次访问的点。
[[DFSAncestorIndex]] 一个 整数empty 仅在 Link 和 Evaluate 期间使用的辅助字段。如果 [[Status]]linkingevaluating, 这是模块自己的 [[DFSIndex]] 或同一强连通分量中"较早"模块的该值。
[[RequestedModules]] ModuleRequest RecordsList 与此模块中的导入关联的 ModuleRequest RecordsList。该 List 按导入的源文本出现顺序排列。
[[LoadedModules]] LoadedModuleRequest RecordsList 从此记录表示的模块用于请求导入具有相对导入属性的模块的说明符字符串到已解析的 Module Record 的映射。该列表不包含两个不同的 Records r1r2,使得 ModuleRequestsEqual(r1, r2) 为 true
[[CycleRoot]] 一个 Cyclic Module Recordempty 循环的第一个访问模块,强连通分量的根 DFS 祖先。对于不在循环中的模块,这将是模块本身。一旦 Evaluate 完成,模块的 [[DFSAncestorIndex]] 是其 [[CycleRoot]][[DFSIndex]]
[[HasTLA]] 一个布尔值 此模块是否单独异步(例如,如果它是包含顶级等待的 Source Text Module Record)。具有异步依赖项并不意味着此字段为 true。此字段在模块解析后不得更改。
[[AsyncEvaluationOrder]] unset、一个 整数done 此字段初始设置为 unset,对于完全同步的模块保持 unset。对于自身异步或具有异步依赖项的模块,它设置为一个 整数,该整数确定 16.2.1.6.1.3.4 排队执行待处理模块的顺序。 一旦待处理模块被执行,该字段设置为 done
[[TopLevelCapability]] 一个 PromiseCapability Recordempty 如果此模块是某个循环的 [[CycleRoot]],并且在该循环中的某个模块上调用了 Evaluate(),此字段包含该整个求值的 PromiseCapability Record。它用于解决从 Evaluate() 抽象方法返回的 Promise 对象。除非为这些依赖项中的某些启动了顶级 Evaluate(),否则该字段对于该模块的任何依赖项都将是 empty
[[AsyncParentModules]] Cyclic Module RecordsList 如果此模块或依赖项的 [[HasTLA]]true,并且执行正在进行中,这会跟踪此模块的顶级执行作业的父导入器。这些父模块在此模块成功完成执行之前不会开始执行。
[[PendingAsyncDependencies]] 一个 整数empty 如果此模块有任何异步依赖项,这会跟踪此模块剩余要执行的异步依赖模块数量。 当此字段达到 0 且没有执行错误时,具有异步依赖项的模块将被执行。

除了 表 44 中定义的方法外,Cyclic Module Records 还具有 表 46 中列出的附加方法

表 46:Cyclic Module Records 的附加抽象方法
方法 目的
InitializeEnvironment() 初始化模块的 Environment Record,包括解析所有导入的绑定,并创建模块的 执行上下文
ExecuteModule([promiseCapability]) 在其 执行上下文 内求值模块的代码。 如果此模块的 [[HasTLA]]true,则传递一个 PromiseCapability Record 作为参数,并且期望该方法解析或拒绝给定的能力。在这种情况下,该方法不得抛出异常,而应在必要时拒绝 PromiseCapability Record

GraphLoadingState Record 是一个 Record,包含有关模块图加载过程的信息。它用于在调用 HostLoadImportedModule 后继续加载。每个 GraphLoadingState Record 都有 表 47 中定义的字段:

表 47:GraphLoadingState Record 字段
字段名称 值类型 含义
[[PromiseCapability]] 一个 PromiseCapability Record 加载过程完成时要解析的 promise。
[[IsLoading]] 一个布尔值 如果加载过程尚未完成,无论是成功还是出现错误,它都是 true。
[[PendingModulesCount]] 一个非负 整数 它跟踪待处理的 HostLoadImportedModule 调用数量。
[[Visited]] Cyclic Module RecordsList 它是当前加载过程已加载的 Cyclic Module Records 的列表,以避免循环依赖的无限循环。
[[HostDefined]] 任何内容(默认值为 empty 它包含从 LoadRequestedModules 调用者传递到 HostLoadImportedModule宿主定义 数据。

16.2.1.6.1 Module Record 抽象方法的实现

以下是 Cyclic Module Record 的具体方法,它们实现了 表 44 中定义的相应 Module Record 抽象方法。

16.2.1.6.1.1 LoadRequestedModules ( [ hostDefined ] )

Cyclic Module Record module 的 LoadRequestedModules 具体方法接受可选参数 hostDefined(任何内容)并返回一个 Promise。它填充 module 依赖图中所有 Module Records[[LoadedModules]](大部分工作由辅助函数 InnerModuleLoading 完成)。它接受一个可选的 hostDefined 参数,该参数传递给 HostLoadImportedModule 钩子。调用时执行以下步骤:

  1. 如果 hostDefined 不存在,让 hostDefinedempty
  2. pc 为 ! NewPromiseCapability(%Promise%)。
  3. stateGraphLoadingState Record { [[IsLoading]]: true[[PendingModulesCount]]: 1,[[Visited]]: « »,[[PromiseCapability]]: pc[[HostDefined]]: hostDefined }。
  4. 执行 InnerModuleLoading(state, module)。
  5. 返回 pc.[[Promise]]
注意
hostDefined 参数可用于传递获取导入模块所需的附加信息。例如,HTML 使用它为 <link rel="preload" as="..."> 标签设置正确的 fetch 目标。 import() 表达式从不设置 hostDefined 参数。

16.2.1.6.1.1.1 InnerModuleLoading ( state, module )

抽象操作 InnerModuleLoading 接受参数 state(一个 GraphLoadingState Record)和 module(一个 Module Record)并返回 unused。它被 LoadRequestedModules 用于递归执行 module 依赖图的实际加载过程。调用时执行以下步骤:

  1. 断言state.[[IsLoading]]true
  2. 如果 moduleCyclic Module Recordmodule.[[Status]]new,并且 state.[[Visited]] 不包含 module,那么
    1. module 追加到 state.[[Visited]]
    2. requestedModulesCountmodule.[[RequestedModules]] 中的元素数量。
    3. 设置 state.[[PendingModulesCount]]state.[[PendingModulesCount]] + requestedModulesCount
    4. 对于 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
      1. 如果 AllImportAttributesSupported(request.[[Attributes]]) 是 false,那么
        1. errorThrowCompletion(一个新创建的 SyntaxError 对象)。
        2. 执行 ContinueModuleLoading(state, error)。
      2. 否则,如果 module.[[LoadedModules]] 包含一个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, request) 是 true,那么
        1. 执行 InnerModuleLoading(state, record.[[Module]])。
      3. 否则,
        1. 执行 HostLoadImportedModule(module, request, state.[[HostDefined]], state)。
        2. 注意:HostLoadImportedModule 将调用 FinishLoadingImportedModule, 它通过 ContinueModuleLoading 重新进入图加载过程。
      4. 如果 state.[[IsLoading]]false,返回 unused
  3. 断言state.[[PendingModulesCount]] ≥ 1。
  4. 设置 state.[[PendingModulesCount]]state.[[PendingModulesCount]] - 1。
  5. 如果 state.[[PendingModulesCount]] = 0,那么
    1. 设置 state.[[IsLoading]]false
    2. 对于 state.[[Visited]] 的每个 Cyclic Module Record loaded,执行
      1. 如果 loaded.[[Status]]new,设置 loaded.[[Status]]unlinked
    3. 执行 ! Call(state.[[PromiseCapability]].[[Resolve]], undefined, « undefined »)。
  6. 返回 unused

16.2.1.6.1.1.2 ContinueModuleLoading ( state, moduleCompletion )

抽象操作 ContinueModuleLoading 接受参数 state(一个 GraphLoadingState Record)和 moduleCompletion(一个 包含 Module Record正常完成 或一个 抛出 完成)并返回 unused。它用于在调用 HostLoadImportedModule 后重新进入加载过程。 调用时执行以下步骤:

  1. 如果 state.[[IsLoading]]false,返回 unused
  2. 如果 moduleCompletion正常 完成,那么
    1. 执行 InnerModuleLoading(state, moduleCompletion.[[Value]])。
  3. 否则,
    1. 设置 state.[[IsLoading]]false
    2. 执行 ! Call(state.[[PromiseCapability]].[[Reject]], undefined, « moduleCompletion.[[Value]] »)。
  4. 返回 unused

16.2.1.6.1.2 Link ( )

Cyclic Module Record module 的 Link 具体方法不接受参数,并返回一个 包含 unused正常 完成 或一个 抛出 完成。成功时,Link 将此模块的 [[Status]]unlinked 转换为 linked。失败时,抛出异常并且此模块的 [[Status]] 保持为 unlinked。(大部分工作由辅助函数 InnerModuleLinking 完成。)调用时执行以下步骤:

  1. 断言module.[[Status]]unlinkedlinkedevaluating-asyncevaluated 之一。
  2. stack 为一个新的空 List
  3. resultCompletion(InnerModuleLinking(module, stack, 0))。
  4. 如果 result突然完成,那么
    1. 对于 stack 的每个 Cyclic Module Record m,执行
      1. 断言m.[[Status]]linking
      2. 设置 m.[[Status]]unlinked
    2. 断言module.[[Status]]unlinked
    3. 返回 ? result
  5. 断言module.[[Status]]linkedevaluating-asyncevaluated 之一。
  6. 断言stack 是空的。
  7. 返回 unused

16.2.1.6.1.2.1 InnerModuleLinking ( module, stack, index )

抽象操作 InnerModuleLinking 接受参数 module(一个 Module Record)、 stackCyclic Module RecordsList)和 index(一个非负 整数),并返回一个 包含 非负 整数正常完成 或一个 抛出 完成。它被 Link 用于对 module 以及依赖图中的所有其他模块递归执行实际的链接过程。stackindex 参数,以及模块的 [[DFSIndex]][[DFSAncestorIndex]] 字段,跟踪深度优先搜索(DFS)遍历。特别地,[[DFSAncestorIndex]] 用于发现强连通分量(SCC),使得 SCC 中的所有模块一起转换为 linked。调用时执行以下步骤:

  1. 如果 module 不是 Cyclic Module Record,那么
    1. 执行 ? module.Link()。
    2. 返回 index
  2. 如果 module.[[Status]]linkinglinkedevaluating-asyncevaluated 之一,那么
    1. 返回 index
  3. 断言module.[[Status]]unlinked
  4. 设置 module.[[Status]]linking
  5. 设置 module.[[DFSIndex]]index
  6. 设置 module.[[DFSAncestorIndex]]index
  7. 设置 indexindex + 1。
  8. module 追加到 stack
  9. 对于 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
    1. requiredModuleGetImportedModule(module, request)。
    2. 设置 index 为 ? InnerModuleLinking(requiredModule, stack, index)。
    3. 如果 requiredModuleCyclic Module Record,那么
      1. 断言requiredModule.[[Status]]linkinglinkedevaluating-asyncevaluated 之一。
      2. 断言requiredModule.[[Status]]linking 当且仅当 stack 包含 requiredModule
      3. 如果 requiredModule.[[Status]]linking,那么
        1. 设置 module.[[DFSAncestorIndex]]min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
  10. 执行 ? module.InitializeEnvironment()。
  11. 断言modulestack 中恰好出现一次。
  12. 断言module.[[DFSAncestorIndex]]module.[[DFSIndex]]
  13. 如果 module.[[DFSAncestorIndex]] = module.[[DFSIndex]],那么
    1. donefalse
    2. 重复,当 donefalse 时,
      1. requiredModulestack 的最后一个元素。
      2. 移除 stack 的最后一个元素。
      3. 断言requiredModuleCyclic Module Record
      4. 设置 requiredModule.[[Status]]linked
      5. 如果 requiredModulemodule 是同一个 Module Record,设置 donetrue
  14. 返回 index

16.2.1.6.1.3 Evaluate ( )

Cyclic Module Record module 的 Evaluate 具体方法不接受参数并返回一个 Promise。Evaluate 将此模块的 [[Status]]linked 转换为 evaluating-asyncevaluated。当第一次在给定强连通分量中的模块上调用时,Evaluate 创建并返回一个 Promise,该 Promise 在模块完成求值时解析。此 Promise 存储在该分量的 [[CycleRoot]][[TopLevelCapability]] 字段中。在该分量中任何模块上后续调用 Evaluate 都会返回相同的 Promise。(大部分工作由辅助函数 InnerModuleEvaluation 完成。)调用时执行以下步骤:

  1. 断言:此次 Evaluate 调用不会与 surrounding agent 内的另一次 Evaluate 调用同时发生。
  2. 断言module.[[Status]]linkedevaluating-asyncevaluated 之一。
  3. 如果 module.[[Status]]evaluating-asyncevaluated, 设置 modulemodule.[[CycleRoot]]
  4. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 返回 module.[[TopLevelCapability]].[[Promise]]
  5. stack 为一个新的空 List
  6. capability 为 ! NewPromiseCapability(%Promise%)。
  7. 设置 module.[[TopLevelCapability]]capability
  8. resultCompletion(InnerModuleEvaluation(module, stack, 0))。
  9. 如果 result突然完成,那么
    1. 对于 stack 的每个 Cyclic Module Record m,执行
      1. 断言m.[[Status]]evaluating
      2. 断言m.[[AsyncEvaluationOrder]]unset
      3. 设置 m.[[Status]]evaluated
      4. 设置 m.[[EvaluationError]]result
    2. 断言module.[[Status]]evaluated
    3. 断言module.[[EvaluationError]]result 是相同的 Completion Record
    4. 执行 ! Call(capability.[[Reject]], undefined, « result.[[Value]] »)。
  10. 否则,
    1. 断言module.[[Status]]evaluating-asyncevaluated
    2. 断言module.[[EvaluationError]]empty
    3. 如果 module.[[Status]]evaluated,那么
      1. 注意:这意味着 module 的求值同步完成。
      2. 断言module.[[AsyncEvaluationOrder]]unset
      3. 执行 ! Call(capability.[[Resolve]], undefined, « undefined »)。
    4. 断言stack 是空的。
  11. 返回 capability.[[Promise]]

16.2.1.6.1.3.1 InnerModuleEvaluation ( module, stack, index )

抽象操作 InnerModuleEvaluation 接受参数 module(一个 Module Record)、 stackCyclic Module RecordsList)和 index(一个非负 整数),并返回一个 包含 非负 整数正常完成 或一个 抛出 完成。它被 Evaluate 用于对 module 以及依赖图中的所有其他模块递归执行实际的求值过程。stackindex 参数,以及 module[[DFSIndex]][[DFSAncestorIndex]] 字段,其使用方式与 InnerModuleLinking 中相同。调用时执行以下步骤:

  1. 如果 module 不是 Cyclic Module Record,那么
    1. 执行 ? EvaluateModuleSync(module)。
    2. 返回 index
  2. 如果 module.[[Status]]evaluating-asyncevaluated,那么
    1. 如果 module.[[EvaluationError]]empty,返回 index
    2. 否则,返回 ? module.[[EvaluationError]]
  3. 如果 module.[[Status]]evaluating,返回 index
  4. 断言module.[[Status]]linked
  5. 设置 module.[[Status]]evaluating
  6. 设置 module.[[DFSIndex]]index
  7. 设置 module.[[DFSAncestorIndex]]index
  8. 设置 module.[[PendingAsyncDependencies]] 为 0。
  9. 设置 indexindex + 1。
  10. module 追加到 stack
  11. 对于 module.[[RequestedModules]] 的每个 ModuleRequest Record request,执行
    1. requiredModuleGetImportedModule(module, request)。
    2. 设置 index 为 ? InnerModuleEvaluation(requiredModule, stack, index)。
    3. 如果 requiredModuleCyclic Module Record,那么
      1. 断言requiredModule.[[Status]]evaluatingevaluating-asyncevaluated 之一。
      2. 断言requiredModule.[[Status]]evaluating 当且仅当 stack 包含 requiredModule
      3. 如果 requiredModule.[[Status]]evaluating,那么
        1. 设置 module.[[DFSAncestorIndex]]min(module.[[DFSAncestorIndex]], requiredModule.[[DFSAncestorIndex]])。
      4. 否则,
        1. 设置 requiredModulerequiredModule.[[CycleRoot]]
        2. 断言requiredModule.[[Status]]evaluating-asyncevaluated
        3. 如果 requiredModule.[[EvaluationError]] 不是 empty,返回 ? requiredModule.[[EvaluationError]]
      5. 如果 requiredModule.[[AsyncEvaluationOrder]]整数,那么
        1. 设置 module.[[PendingAsyncDependencies]]module.[[PendingAsyncDependencies]] + 1。
        2. module 追加到 requiredModule.[[AsyncParentModules]]
  12. 如果 module.[[PendingAsyncDependencies]] > 0 或 module.[[HasTLA]]true,那么
    1. 断言module.[[AsyncEvaluationOrder]]unset
    2. 设置 module.[[AsyncEvaluationOrder]]IncrementModuleAsyncEvaluationCount()。
    3. 如果 module.[[PendingAsyncDependencies]] = 0, 执行 ExecuteAsyncModule(module)。
  13. 否则,
    1. 执行 ? module.ExecuteModule()
  14. 断言modulestack 中恰好出现一次。
  15. 断言module.[[DFSAncestorIndex]]module.[[DFSIndex]]
  16. 如果 module.[[DFSAncestorIndex]] = module.[[DFSIndex]],那么
    1. donefalse
    2. 重复,当 donefalse 时,
      1. requiredModulestack 的最后一个元素。
      2. 移除 stack 的最后一个元素。
      3. 断言requiredModuleCyclic Module Record
      4. 断言requiredModule.[[AsyncEvaluationOrder]]整数unset
      5. 如果 requiredModule.[[AsyncEvaluationOrder]]unset,设置 requiredModule.[[Status]]evaluated
      6. 否则,设置 requiredModule.[[Status]]evaluating-async
      7. 如果 requiredModulemodule 是同一个 Module Record,设置 donetrue
      8. 设置 requiredModule.[[CycleRoot]]module
  17. 返回 index
注意 1

模块在被 InnerModuleEvaluation 遍历时处于 evaluating 状态。模块在执行完成时处于 evaluated 状态,或者在执行期间如果其 [[HasTLA]] 字段为 true 或具有异步依赖时处于 evaluating-async 状态。

注意 2

当异步循环不是 evaluating 时,依赖于异步循环模块的任何模块将通过 [[CycleRoot]] 依赖于循环根的执行。这确保循环状态可以通过其根模块状态作为单个强连通分量进行处理。

16.2.1.6.1.3.2 ExecuteAsyncModule ( module )

抽象操作 ExecuteAsyncModule 接受参数 module(一个 Cyclic Module Record)并返回 unused。调用时执行以下步骤:

  1. 断言module.[[Status]]evaluatingevaluating-async
  2. 断言module.[[HasTLA]]true
  3. capability 为 ! NewPromiseCapability(%Promise%)。
  4. fulfilledClosure 为一个新的 Abstract Closure, 不接受参数,捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionFulfilled(module)。
    2. 返回 undefined
  5. onFulfilledCreateBuiltinFunction(fulfilledClosure, 0, "", « »)。
  6. rejectedClosure 为一个新的 Abstract Closure, 接受参数 (error),捕获 module,并在调用时执行以下步骤:
    1. 执行 AsyncModuleExecutionRejected(module, error)。
    2. 返回 undefined
  7. onRejectedCreateBuiltinFunction(rejectedClosure, 0, "", « »)。
  8. 执行 PerformPromiseThen(capability.[[Promise]], onFulfilled, onRejected)。
  9. 执行 ! module.ExecuteModule(capability)。
  10. 返回 unused

16.2.1.6.1.3.3 GatherAvailableAncestors ( module, execList )

抽象操作 GatherAvailableAncestors 接受参数 module (一个 Cyclic Module Record)和 execListCyclic Module RecordsList)并返回 unused。调用时执行以下步骤:

  1. 对于 module.[[AsyncParentModules]] 的每个 Cyclic Module Record m,执行
    1. 如果 execList 不包含 mm.[[CycleRoot]].[[EvaluationError]]empty,那么
      1. 断言m.[[Status]]evaluating-async
      2. 断言m.[[EvaluationError]]empty
      3. 断言m.[[AsyncEvaluationOrder]]整数
      4. 断言m.[[PendingAsyncDependencies]] > 0。
      5. 设置 m.[[PendingAsyncDependencies]]m.[[PendingAsyncDependencies]] - 1。
      6. 如果 m.[[PendingAsyncDependencies]] = 0,那么
        1. m 追加到 execList
        2. 如果 m.[[HasTLA]]false,执行 GatherAvailableAncestors(m, execList)。
  2. 返回 unused
注意

当根 module 的异步执行完成时,此函数确定能够在此完成时同步执行的模块列表,将它们填充到 execList 中。

16.2.1.6.1.3.4 AsyncModuleExecutionFulfilled ( module )

抽象操作 AsyncModuleExecutionFulfilled 接受参数 module(一个 Cyclic Module Record)并返回 unused。调用时执行以下步骤:

  1. 如果 module.[[Status]]evaluated,那么
    1. 断言module.[[EvaluationError]] 不是 empty
    2. 返回 unused
  2. 断言module.[[Status]]evaluating-async
  3. 断言module.[[AsyncEvaluationOrder]]整数
  4. 断言module.[[EvaluationError]]empty
  5. 设置 module.[[AsyncEvaluationOrder]]done
  6. 设置 module.[[Status]]evaluated
  7. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 断言module.[[CycleRoot]]module 是同一个 Module Record
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  8. execList 为一个新的空 List
  9. 执行 GatherAvailableAncestors(module, execList)。
  10. 断言execList 的所有元素都将其 [[AsyncEvaluationOrder]] 字段设置为 整数[[PendingAsyncDependencies]] 字段设置为 0,[[EvaluationError]] 字段设置为 empty
  11. sortedExecList 为一个 List, 其元素是 execList 的元素,按其 [[AsyncEvaluationOrder]] 字段升序排序。
  12. 对于 sortedExecList 的每个 Cyclic Module Record m,执行
    1. 如果 m.[[Status]]evaluated,那么
      1. 断言m.[[EvaluationError]] 不是 empty
    2. 否则,如果 m.[[HasTLA]]true,那么
      1. 执行 ExecuteAsyncModule(m)。
    3. 否则,
      1. resultm.ExecuteModule()
      2. 如果 result突然完成,那么
        1. 执行 AsyncModuleExecutionRejected(m, result.[[Value]])。
      3. 否则,
        1. 设置 m.[[AsyncEvaluationOrder]]done
        2. 设置 m.[[Status]]evaluated
        3. 如果 m.[[TopLevelCapability]] 不是 empty,那么
          1. 断言m.[[CycleRoot]]m 是同一个 Module Record
          2. 执行 ! Call(m.[[TopLevelCapability]].[[Resolve]], undefined, « undefined »)。
  13. 返回 unused

16.2.1.6.1.3.5 AsyncModuleExecutionRejected ( module, error )

抽象操作 AsyncModuleExecutionRejected 接受参数 module(一个 Cyclic Module Record)和 error(一个 ECMAScript 语言值)并返回 unused。调用时执行以下步骤:

  1. 如果 module.[[Status]]evaluated,那么
    1. 断言module.[[EvaluationError]] 不是 empty
    2. 返回 unused
  2. 断言module.[[Status]]evaluating-async
  3. 断言module.[[AsyncEvaluationOrder]]整数
  4. 断言module.[[EvaluationError]]empty
  5. 设置 module.[[EvaluationError]]ThrowCompletion(error)。
  6. 设置 module.[[Status]]evaluated
  7. 设置 module.[[AsyncEvaluationOrder]]done
  8. 注意:module.[[AsyncEvaluationOrder]] 设置为 done 是为了与 AsyncModuleExecutionFulfilled 保持对称。 在 InnerModuleEvaluation 中, 当模块的 [[EvaluationError]] 内部槽不是 empty 时,其 [[AsyncEvaluationOrder]] 内部槽的值未被使用。
  9. 对于 module.[[AsyncParentModules]] 的每个 Cyclic Module Record m,执行
    1. 执行 AsyncModuleExecutionRejected(m, error)。
  10. 如果 module.[[TopLevelCapability]] 不是 empty,那么
    1. 断言module.[[CycleRoot]]module 是同一个 Module Record
    2. 执行 ! Call(module.[[TopLevelCapability]].[[Reject]], undefined, « error »)。
  11. 返回 unused

16.2.1.6.2 循环模块记录图示例

这个非规范性章节提供了一系列常见模块图链接和求值的示例,特别关注错误如何发生。

首先考虑以下简单的模块图:

图 2:一个简单的模块图
一个模块图,其中模块 A 依赖于模块 B,模块 B 依赖于模块 C

让我们首先假设没有错误条件。当 宿主 首次调用 A.LoadRequestedModules() 时,这将按假设成功完成,并递归加载 BC 的依赖(分别是 C 和无),然后设置 A.[[Status]] = B.[[Status]] = C.[[Status]] = unlinked。 然后,当 宿主 调用 A.Link() 时,它将成功完成(再次按假设),使得 A.[[Status]] = B.[[Status]] = C.[[Status]] = linked。这些准备步骤可以在任何时候执行。稍后,当 宿主 准备承担模块的任何可能副作用时,它可以调用 A.Evaluate(),这将成功完成,返回一个解析为 undefined 的 Promise(再次按假设),递归地首先求值 C,然后是 B。此时每个模块的 [[Status]] 将是 evaluated

然后考虑在成功调用 A.LoadRequestedModules() 后涉及链接错误的情况。如果 CInnerModuleLinking 成功,但之后 B 失败,例如因为它导入了 C 不提供的内容,那么原始的 A.Link() 将失败,AB[[Status]] 保持 unlinked。 不过,C[[Status]] 已变为 linked

最后,考虑在成功调用 Link() 后涉及求值错误的情况。如果 CInnerModuleEvaluation 成功,但之后 B 失败,例如因为 B 包含抛出异常的代码,那么原始的 A.Evaluate() 将失败,返回一个被拒绝的 Promise。生成的异常将记录在 AB[[EvaluationError]] 字段中,它们的 [[Status]] 将变为 evaluatedC 也将变为 evaluated,但与 AB 相反,它将保持没有 [[EvaluationError]],因为它成功完成了求值。 存储异常确保任何时候 宿主 尝试通过调用它们的 Evaluate() 方法重用 AB 时,它将遇到相同的异常。(宿主 不需要重用 Cyclic Module Records;类似地,宿主 不需要暴露这些方法抛出的异常对象。然而,规范启用了这样的用法。)

现在考虑一种不同类型的错误条件:

图 3:具有无法解析模块的模块图
一个模块图,其中模块 A 依赖于一个缺失(无法解析)的模块,用 ??? 表示

在这种情况下,模块 A 声明对某个其他模块的依赖,但该模块不存在 Module Record,即 HostLoadImportedModule 在被询问时调用 FinishLoadingImportedModule 时传递异常。这可能由于各种原因发生,例如对应的资源不存在,或者资源存在但 ParseModule 在尝试解析生成的源文本时返回一些错误。宿主 可以选择通过传递给 FinishLoadingImportedModule 的完成来暴露失败原因。 在任何情况下,这个异常导致加载失败,这使得 A[[Status]] 保持 new

这里加载、链接和求值错误之间的差异是由于以下特征:

  • 求值 必须只执行一次,因为它可能导致副作用;因此记住求值是否已经执行很重要,即使不成功。(在错误情况下,记住异常也是有意义的,因为否则后续的 Evaluate() 调用将必须合成一个新的异常。)
  • 另一方面,链接是无副作用的,因此即使失败,也可以稍后重试而不会有问题。
  • 加载与 宿主 密切交互,对于其中一些,可能希望允许用户重试失败的加载(例如,如果失败是由临时不良网络条件引起的)。

现在,考虑一个有循环的模块图:

图 4:循环模块图
一个模块图,其中模块 A 依赖于模块 B 和 C,但模块 B 也依赖于模块 A

这里我们假设入口点是模块 A,因此 宿主 通过调用 A.LoadRequestedModules() 进行,这对 A 执行 InnerModuleLoading。 这反过来对 BC 调用 InnerModuleLoading。 由于循环,这再次对 A 触发 InnerModuleLoading, 但此时它是无操作的,因为 A 的依赖加载已经在这个 LoadRequestedModules 过程中被触发。当图中的所有模块都被成功加载时,它们的 [[Status]] 同时从 new 转换为 unlinked

然后 宿主 通过调用 A.Link() 继续,这对 A 执行 InnerModuleLinking。 这反过来对 B 调用 InnerModuleLinking。 由于循环,这再次对 A 触发 InnerModuleLinking, 但此时它是无操作的,因为 A.[[Status]] 已经是 linking。 当控制回到 A 并且对 C 触发 InnerModuleLinking 时,B.[[Status]] 本身保持 linking。 在这返回后,C.[[Status]]linkedAB 一起从 linking 转换为 linked;这是设计如此,因为它们形成强连通分量。可以同时转换同一 SCC 中模块的状态,因为在这个阶段,模块图通过深度优先搜索遍历。

在成功情况下,循环模块图的求值阶段也发生类似的故事。

现在考虑 A 有链接错误的情况;例如,它尝试从 C 导入一个不存在的绑定。在这种情况下,上述步骤仍然发生,包括从第二次对 A 调用 InnerModuleLinking 的早期返回。 然而,一旦我们展开回到对 A 的原始 InnerModuleLinking, 它在 InitializeEnvironment 期间失败,即在 C.ResolveExport() 之后立即。抛出的 SyntaxError 异常传播到 A.Link,它重置当前在其 stack 上的所有模块(这些总是正好是仍然 linking 的模块)。因此 AB 都变为 unlinked。注意 C 保持为 linked

或者,考虑 A 有求值错误的情况;例如,它的源代码抛出异常。在这种情况下,上述步骤的求值时类似仍然发生,包括从第二次对 A 调用 InnerModuleEvaluation 的早期返回。 然而,一旦我们展开回到对 A 的原始 InnerModuleEvaluation, 它按假设失败。抛出的异常传播到 A.Evaluate(),它将错误记录在当前在其 stack 上的所有模块(即仍然 evaluating 的模块)以及通过 [[AsyncParentModules]] 中,这形成了一个链,用于包含或依赖顶层 await 的模块,通过 AsyncModuleExecutionRejected 算法贯穿整个依赖图。因此 AB 都变为 evaluated,异常记录在 AB[[EvaluationError]] 字段中,而 C 保持为 evaluated,没有 [[EvaluationError]]

最后,考虑一个有循环的模块图,其中所有模块都异步完成:

图 5:异步循环模块图
一个模块图,其中模块 A 依赖于模块 B 和 C,模块 B 依赖于模块 D,模块 C 依赖于模块 D 和 E,模块 D 依赖于模块 A

加载和链接像之前一样发生,所有模块最终的 [[Status]] 设置为 linked

调用 A.Evaluate() 对 ABD 调用 InnerModuleEvaluation, 它们都转换为 evaluating。然后再次对 A 调用 InnerModuleEvaluation, 这是无操作的,因为它已经是 evaluating。此时,D.[[PendingAsyncDependencies]] 是 0,因此调用 ExecuteAsyncModule(D), 我们用一个新的 PromiseCapability 调用 D.ExecuteModule,跟踪 D 的异步执行。我们展开回到对 BInnerModuleEvaluation, 设置 B.[[PendingAsyncDependencies]] 为 1,B.[[AsyncEvaluationOrder]] 为 1。我们展开回到对 A 的原始 InnerModuleEvaluation, 设置 A.[[PendingAsyncDependencies]] 为 1。在 A 依赖项循环的下一次迭代中,我们对 C 调用 InnerModuleEvaluation, 因此对 D(再次无操作)和 E。由于 E 没有依赖项且不是循环的一部分,我们以与 D 相同的方式调用 ExecuteAsyncModule(E), E 立即从堆栈中移除。我们再次展开到对 CInnerModuleEvaluation, 设置 C.[[AsyncEvaluationOrder]] 为 3。现在我们完成对 A 依赖项的循环,设置 A.[[AsyncEvaluationOrder]] 为 4,并从堆栈中移除整个强连通分量,同时将所有模块转换为 evaluating-async。此时,模块的字段如 表 48 所示。

表 48:初始 Evaluate() 调用后的模块字段
字段
模块
A B C D E
[[DFSIndex]] 0 1 3 2 4
[[DFSAncestorIndex]] 0 0 0 0 4
[[Status]] evaluating-async evaluating-async evaluating-async evaluating-async evaluating-async
[[AsyncEvaluationOrder]] 4 1 3 0 2
[[AsyncParentModules]] « » « A » « A » « B, C » « C »
[[PendingAsyncDependencies]] 2(BC 1(D 2(DE 0 0

让我们假设 E 首先完成执行。当发生这种情况时,调用 AsyncModuleExecutionFulfilledE.[[Status]] 设置为 evaluatedC.[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 49 所示。

表 49:模块 E 完成执行后的模块字段
字段
模块
C E
[[DFSIndex]] 3 4
[[DFSAncestorIndex]] 0 4
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 3 2
[[AsyncParentModules]] « A » « C »
[[PendingAsyncDependencies]] 1(D 0

D 接下来完成(因为它是唯一仍在执行的模块)。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledD.[[Status]] 设置为 evaluated。其可用于执行的祖先是 B (其 [[AsyncEvaluationOrder]] 是 1)和 C (其 [[AsyncEvaluationOrder]] 是 3),因此 B 将首先处理: B.[[PendingAsyncDependencies]] 递减为 0,对 B 调用 ExecuteAsyncModule, 它开始执行。C.[[PendingAsyncDependencies]] 也递减为 0,C 开始执行(如果 B 包含 await,可能与 B 并行)。更新模块的字段如 表 50 所示。

表 50:模块 D 完成执行后的模块字段
字段
模块
B C D
[[DFSIndex]] 1 3 2
[[DFSAncestorIndex]] 0 0 0
[[Status]] evaluating-async evaluating-async evaluated
[[AsyncEvaluationOrder]] 1 3 0
[[AsyncParentModules]] « A » « A » « B, C »
[[PendingAsyncDependencies]] 0 0 0

让我们假设 C 接下来完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledC.[[Status]] 设置为 evaluatedA.[[PendingAsyncDependencies]] 递减为 1。更新模块的字段如 表 51 所示。

表 51:模块 C 完成执行后的模块字段
字段
模块
A C
[[DFSIndex]] 0 3
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 3
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0

然后,B 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledB.[[Status]] 设置为 evaluatedA.[[PendingAsyncDependencies]] 递减为 0,因此调用 ExecuteAsyncModule, 它开始执行。更新模块的字段如 表 52 所示。

表 52:模块 B 完成执行后的模块字段
字段
模块
A B
[[DFSIndex]] 0 1
[[DFSAncestorIndex]] 0 0
[[Status]] evaluating-async evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0

最后,A 完成执行。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledA.[[Status]] 设置为 evaluated。此时,A.[[TopLevelCapability]] 中的 Promise(从 A.Evaluate() 返回)被解析,这结束了对此模块图的处理。更新模块的字段如 表 53 所示。

表 53:模块 A 完成执行后的模块字段
字段
模块
A
[[DFSIndex]] 0
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] 4
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0

或者,考虑失败情况,其中 CB 完成执行之前执行失败并返回错误。当发生这种情况时,调用 AsyncModuleExecutionRejected, 它设置 C.[[Status]]evaluatedC.[[EvaluationError]] 为错误。然后通过对每个 AsyncParentModules 执行 AsyncModuleExecutionRejected 将此错误传播到所有 AsyncParentModules。更新模块的字段如 表 54 所示。

表 54:模块 C 出错完成后的模块字段
字段
模块
A C
[[DFSIndex]] 0 3
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 3
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 1(B 0
[[EvaluationError]] empty C 的求值错误

A 将被拒绝,错误与 C 相同,因为 C 将用 C 的错误对 A 调用 AsyncModuleExecutionRejectedA.[[Status]] 设置为 evaluated。此时 A.[[TopLevelCapability]] 中的 Promise(从 A.Evaluate() 返回)被拒绝。更新模块的字段如 表 55 所示。

表 55:模块 A 被拒绝后的模块字段
字段
模块
A
[[DFSIndex]] 0
[[DFSAncestorIndex]] 0
[[Status]] evaluated
[[AsyncEvaluationOrder]] 4
[[AsyncParentModules]] « »
[[PendingAsyncDependencies]] 0
[[EvaluationError]] C求值 错误

然后,B 完成执行且没有错误。当发生这种情况时,再次调用 AsyncModuleExecutionFulfilledB.[[Status]] 设置为 evaluated。对 B 调用 GatherAvailableAncestors。 然而,A.[[CycleRoot]]A,它有求值错误,因此它不会被添加到返回的 sortedExecList 中,AsyncModuleExecutionFulfilled 将返回而不进行进一步处理。B 的任何未来导入者将从 C 设置在循环根 A 上的求值错误中解析 B.[[CycleRoot]].[[EvaluationError]] 的拒绝。更新模块的字段如 表 56 所示。

表 56:模块 B 在错误图中完成执行后的模块字段
字段
模块
A B
[[DFSIndex]] 0 1
[[DFSAncestorIndex]] 0 0
[[Status]] evaluated evaluated
[[AsyncEvaluationOrder]] 4 1
[[AsyncParentModules]] « » « A »
[[PendingAsyncDependencies]] 0 0
[[EvaluationError]] C求值 错误 empty

16.2.1.7 源文本模块记录

源文本模块记录用于表示从使用 目标符号 Module 解析的 ECMAScript 源文本11)定义的模块信息。其字段包含关于模块导入和导出名称的摘要信息,其具体方法使用这些摘要来链接和求值模块。

源文本模块记录可以与抽象 Module Record 类型的其他子类存在于模块图中,并且可以与 Cyclic Module Record 类型的其他子类参与循环。

除了在 表 45 中定义的字段外,源文本模块记录还有在 表 57 中列出的其他字段。每个字段最初在 ParseModule 中设置。

表 57:源文本模块记录的附加字段
字段名称 值类型 含义
[[ECMAScriptCode]] 一个 解析节点 使用 Module 作为 目标符号 解析此模块源文本的结果。
[[Context]] 一个 ECMAScript 代码执行上下文empty 与此模块关联的 执行上下文。在模块环境初始化之前为 empty
[[ImportMeta]] 一个对象或 empty 通过 import.meta 元属性暴露的对象。在被 ECMAScript 代码访问之前为 empty
[[ImportEntries]] 一个 列表,包含 ImportEntry 记录 从此模块代码派生的 ImportEntry 记录的 列表
[[LocalExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的声明。
[[IndirectExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的重新导出导入或来自 export * as namespace 声明的导出。
[[StarExportEntries]] 一个 列表,包含 ExportEntry 记录 从此模块代码派生的 ExportEntry 记录的 列表,对应于模块内发生的 export * 声明,不包括 export * as namespace 声明。

ImportEntry 记录是一个 记录,摘要了关于单个声明性导入的信息。每个 ImportEntry 记录都有在 表 58 中定义的字段:

表 58:ImportEntry 记录字段
字段名称 值类型 含义
[[ModuleRequest]] 一个 ModuleRequest 记录 表示 ImportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录
[[ImportName]] 一个字符串或 namespace-object [[ModuleRequest]] 标识的模块导出所需绑定的名称。值 namespace-object 表示导入请求是针对目标模块的命名空间对象。
[[LocalName]] 一个字符串 用于从导入模块内部本地访问导入值的名称。
注 1

表 59 给出了用于表示语法导入形式的 ImportEntry 记录字段的示例:

表 59(信息性):导入形式到 ImportEntry 记录的映射
导入语句形式 [[ModuleRequest]] [[ImportName]] [[LocalName]]
import v from "mod"; "mod" "default" "v"
import * as ns from "mod"; "mod" namespace-object "ns"
import {x} from "mod"; "mod" "x" "x"
import {x as v} from "mod"; "mod" "x" "v"
import "mod"; 不创建 ImportEntry 记录

ExportEntry 记录是一个 记录,摘要了关于单个声明性导出的信息。每个 ExportEntry 记录都有在 表 60 中定义的字段:

表 60:ExportEntry 记录字段
字段名称 值类型 含义
[[ExportName]] 一个字符串或 null 此模块用于导出此绑定的名称。
[[ModuleRequest]] 一个 ModuleRequest 记录null 表示 ExportDeclarationModuleSpecifier 和导入属性的 ModuleRequest 记录。 如果 ExportDeclaration 没有 ModuleSpecifier,则为 null
[[ImportName]] 一个字符串、nullallall-but-default [[ModuleRequest]] 标识的模块导出所需绑定的名称。 如果 ExportDeclaration 没有 ModuleSpecifier,则为 nullall 用于 export * as ns from "mod" 声明。 all-but-default 用于 export * from "mod" 声明。
[[LocalName]] 一个字符串或 null 用于从导入模块内部本地访问导出值的名称。如果导出值在模块内部不可本地访问,则为 null
注 2

表 61 给出了用于表示语法导出形式的 ExportEntry 记录字段的示例:

表 61(信息性):导出形式到 ExportEntry 记录的映射
导出语句形式 [[ExportName]] [[ModuleRequest]] [[ImportName]] [[LocalName]]
export var v; "v" null null "v"
export default function f() {} "default" null null "f"
export default function () {} "default" null null "*default*"
export default 42; "default" null null "*default*"
export {x}; "x" null null "x"
export {v as x}; "x" null null "v"
export {x} from "mod"; "x" "mod" "x" null
export {v as x} from "mod"; "x" "mod" "v" null
export * from "mod"; null "mod" all-but-default null
export * as ns from "mod"; "ns" "mod" all null

以下定义指定了 源文本模块记录所需的具体方法和其他 抽象操作

16.2.1.7.1 ParseModule ( sourceText, realm, hostDefined )

抽象操作 ParseModule 接受参数 sourceTextECMAScript 源文本)、realm(一个 Realm Record)和 hostDefined(任意值),返回一个 源文本模块记录或一个非空的 列表,包含 SyntaxError 对象。它基于将 sourceText 作为 Module 解析的结果创建一个 源文本模块记录。调用时执行以下步骤:

  1. bodyParseText(sourceText, Module)。
  2. 如果 body 是一个错误的 列表,返回 body
  3. requestedModulesbodyModuleRequests
  4. importEntriesbodyImportEntries
  5. importedBoundNamesImportedLocalNames(importEntries)。
  6. indirectExportEntries 为一个新的空 列表
  7. localExportEntries 为一个新的空 列表
  8. starExportEntries 为一个新的空 列表
  9. exportEntriesbodyExportEntries
  10. 对于 exportEntries 中的每个 ExportEntry Record ee,执行
    1. 如果 ee.[[ModuleRequest]]null,那么
      1. 如果 importedBoundNames 不包含 ee.[[LocalName]],那么
        1. ee 附加到 localExportEntries
      2. 否则,
        1. ieimportEntries[[LocalName]]ee.[[LocalName]] 的元素。
        2. 如果 ie.[[ImportName]]namespace-object,那么
          1. 注:这是对导入模块命名空间对象的重新导出。
          2. ee 附加到 localExportEntries
        3. 否则,
          1. 注:这是对单个名称的重新导出。
          2. ExportEntry Record { [[ModuleRequest]]: ie.[[ModuleRequest]], [[ImportName]]: ie.[[ImportName]], [[LocalName]]: null, [[ExportName]]: ee.[[ExportName]] } 附加到 indirectExportEntries
    2. 否则如果 ee.[[ImportName]]all-but-default,那么
      1. 断言ee.[[ExportName]]null
      2. ee 附加到 starExportEntries
    3. 否则,
      1. ee 附加到 indirectExportEntries
  11. asyncbody Contains await
  12. 返回 源文本模块记录 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[CycleRoot]]: empty, [[HasTLA]]: async, [[AsyncEvaluationOrder]]: unset, [[TopLevelCapability]]: empty, [[AsyncParentModules]]: « », [[PendingAsyncDependencies]]: empty, [[Status]]: new, [[EvaluationError]]: empty, [[HostDefined]]: hostDefined, [[ECMAScriptCode]]: body, [[Context]]: empty, [[ImportMeta]]: empty, [[RequestedModules]]: requestedModules, [[LoadedModules]]: « », [[ImportEntries]]: importEntries, [[LocalExportEntries]]: localExportEntries, [[IndirectExportEntries]]: indirectExportEntries, [[StarExportEntries]]: starExportEntries, [[DFSIndex]]: empty, [[DFSAncestorIndex]]: empty }。

实现可能在对该模块源文本求值 ParseModule 之前解析模块源文本并分析其早期错误条件。然而,任何错误的报告都必须推迟到本规范实际对该源文本执行 ParseModule 的时刻。

16.2.1.7.2 模块记录抽象方法的实现

以下是 源文本模块记录的具体方法,实现了 表 44 中定义的相应 模块记录抽象方法。

16.2.1.7.2.1 GetExportedNames ( [ exportStarSet ] )

源文本模块记录 module 的 GetExportedNames 具体方法接受可选参数 exportStarSet(一个包含 源文本模块记录列表),返回一个包含字符串的 列表。调用时执行以下步骤:

  1. 断言module.[[Status]] 不是 new
  2. 如果 exportStarSet 不存在,设 exportStarSet 为一个新的空 列表
  3. 如果 exportStarSet 包含 module,那么
    1. 断言:我们已达到 export * 循环的起点。
    2. 返回一个新的空 列表
  4. module 附加到 exportStarSet
  5. exportedNames 为一个新的空 列表
  6. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言module 为此导出提供直接绑定。
    2. 断言e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 附加到 exportedNames
  7. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言module 为此导出导入特定绑定。
    2. 断言e.[[ExportName]] 不是 null
    3. e.[[ExportName]] 附加到 exportedNames
  8. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ModuleRequest]] 不是 null
    2. requestedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. starNamesrequestedModule.GetExportedNames(exportStarSet)。
    4. 对于 starNames 的每个元素 n,执行
      1. 如果 n 不是 "default",那么
        1. 如果 exportedNames 不包含 n,那么
          1. n 附加到 exportedNames
  9. 返回 exportedNames

GetExportedNames 不会过滤掉或为具有歧义星号导出绑定的名称抛出异常。

16.2.1.7.2.2 ResolveExport ( exportName [ , resolveSet ] )

源文本模块记录 module 的 ResolveExport 具体方法接受参数 exportName(一个字符串)和可选参数 resolveSet(一个包含字段 [[Module]](一个 模块记录)和 [[ExportName]](一个字符串)的 记录列表),返回一个 ResolvedBinding Recordnullambiguous

ResolveExport 尝试将导入绑定解析为实际的定义模块和本地绑定名称。定义模块可能是调用此方法的 模块记录所表示的模块,或该模块导入的其他模块。参数 resolveSet 用于检测未解析的循环导入/导出路径。如果到达的特定 模块记录exportName 的配对已在 resolveSet 中,则遇到了导入循环。在递归调用 ResolveExport 之前,由 moduleexportName 组成的配对会添加到 resolveSet

如果找到定义模块,返回一个 ResolvedBinding Record { [[Module]], [[BindingName]] }。此记录标识最初请求导出的已解析绑定,除非这是没有本地绑定的命名空间导出。在这种情况下,[[BindingName]] 将设置为 namespace。如果没有找到定义或请求被发现是循环的,返回 null。如果请求被发现是歧义的,返回 ambiguous

调用时执行以下步骤:

  1. 断言module.[[Status]] 不是 new
  2. 如果 resolveSet 不存在,设 resolveSet 为一个新的空 列表
  3. 对于 resolveSet 中的每个 记录 { [[Module]], [[ExportName]] } r,执行
    1. 如果 moduler.[[Module]] 是同一个 模块记录exportNamer.[[ExportName]],那么
      1. 断言:这是一个循环导入请求。
      2. 返回 null
  4. 记录 { [[Module]]: module, [[ExportName]]: exportName } 附加到 resolveSet
  5. 对于 module.[[LocalExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 如果 e.[[ExportName]]exportName,那么
      1. 断言module 为此导出提供直接绑定。
      2. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: e.[[LocalName]] }。
  6. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 如果 e.[[ExportName]]exportName,那么
      1. 断言e.[[ModuleRequest]] 不是 null
      2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
      3. 如果 e.[[ImportName]]all,那么
        1. 断言module 不为此导出提供直接绑定。
        2. 返回 ResolvedBinding Record { [[Module]]: importedModule, [[BindingName]]: namespace }。
      4. 否则,
        1. 断言module 为此导出导入特定绑定。
        2. 断言e.[[ImportName]] 是一个字符串
        3. 返回 importedModule.ResolveExport(e.[[ImportName]], resolveSet)。
  7. 如果 exportName"default",那么
    1. 断言:此模块没有显式定义 default 导出。
    2. 返回 null
    3. 注:default 导出不能由 export * from "mod" 声明提供。
  8. starResolutionnull
  9. 对于 module.[[StarExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ModuleRequest]] 不是 null
    2. importedModuleGetImportedModule(module, e.[[ModuleRequest]])。
    3. resolutionimportedModule.ResolveExport(exportName, resolveSet)。
    4. 如果 resolutionambiguous,返回 ambiguous
    5. 如果 resolution 不是 null,那么
      1. 断言resolution 是一个 ResolvedBinding Record
      2. 如果 starResolutionnull,那么
        1. starResolutionresolution
      3. 否则,
        1. 断言:有多个包含请求名称的 * 导入。
        2. 如果 resolution.[[Module]]starResolution.[[Module]] 不是同一个 模块记录,返回 ambiguous
        3. 如果 resolution.[[BindingName]] 不是 starResolution.[[BindingName]]resolution.[[BindingName]]starResolution.[[BindingName]] 中的任一个是 namespace,返回 ambiguous
        4. 如果 resolution.[[BindingName]] 是一个字符串starResolution.[[BindingName]] 是一个字符串,且 resolution.[[BindingName]] 不是 starResolution.[[BindingName]],返回 ambiguous
  10. 返回 starResolution

16.2.1.7.3 循环模块记录抽象方法的实现

以下是 源文本模块记录的具体方法,实现了 表 46 中定义的相应 循环模块记录抽象方法。

16.2.1.7.3.1 InitializeEnvironment ( )

源文本模块记录 module 的 InitializeEnvironment 具体方法不接受参数,返回 包含 unused 的正常完成,或 抛出完成。调用时执行以下步骤:

  1. 对于 module.[[IndirectExportEntries]] 中的每个 ExportEntry Record e,执行
    1. 断言e.[[ExportName]] 不是 null
    2. resolutionmodule.ResolveExport(e.[[ExportName]])。
    3. 如果 resolutionnullambiguous,抛出 SyntaxError 异常。
    4. 断言resolution 是一个 ResolvedBinding Record
  2. 断言module 的所有命名导出都是可解析的。
  3. realmmodule.[[Realm]]
  4. 断言realm 不是 undefined
  5. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  6. module.[[Environment]]env
  7. 对于 module.[[ImportEntries]] 中的每个 ImportEntry Record in,执行
    1. importedModuleGetImportedModule(module, in.[[ModuleRequest]])。
    2. 如果 in.[[ImportName]]namespace-object,那么
      1. namespaceGetModuleNamespace(importedModule)。
      2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
      3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
    3. 否则,
      1. resolutionimportedModule.ResolveExport(in.[[ImportName]])。
      2. 如果 resolutionnullambiguous,抛出 SyntaxError 异常。
      3. 如果 resolution.[[BindingName]]namespace,那么
        1. namespaceGetModuleNamespace(resolution.[[Module]])。
        2. 执行 ! env.CreateImmutableBinding(in.[[LocalName]], true)。
        3. 执行 ! env.InitializeBinding(in.[[LocalName]], namespace)。
      4. 否则,
        1. 执行 CreateImportBinding(env, in.[[LocalName]], resolution.[[Module]], resolution.[[BindingName]])。
  8. moduleContext 为一个新的 ECMAScript 代码执行上下文
  9. moduleContext 的 Function 为 null
  10. 断言module.[[Realm]] 不是 undefined
  11. moduleContextRealmmodule.[[Realm]]
  12. moduleContext 的 ScriptOrModule 为 module
  13. moduleContext 的 VariableEnvironment 为 module.[[Environment]]
  14. moduleContext 的 LexicalEnvironment 为 module.[[Environment]]
  15. moduleContext 的 PrivateEnvironment 为 null
  16. module.[[Context]]moduleContext
  17. moduleContext 压入 执行上下文栈moduleContext 现在是 运行的执行上下文
  18. codemodule.[[ECMAScriptCode]]
  19. varDeclarationscodeVarScopedDeclarations
  20. declaredVarNames 为一个新的空 列表
  21. 对于 varDeclarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 declaredVarNames 不包含 dn,那么
        1. 执行 ! env.CreateMutableBinding(dn, false)。
        2. 执行 ! env.InitializeBinding(dn, undefined)。
        3. dn 附加到 declaredVarNames
  22. lexDeclarationscodeLexicallyScopedDeclarations
  23. privateEnvnull
  24. 对于 lexDeclarations 的每个元素 d,执行
    1. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ! env.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ! env.CreateMutableBinding(dn, false)。
      3. 如果 dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration,那么
        1. fodInstantiateFunctionObject,参数为 envprivateEnv
        2. 执行 ! env.InitializeBinding(dn, fo)。
  25. 执行上下文栈 中移除 moduleContext
  26. 返回 unused

16.2.1.7.3.2 ExecuteModule ( [ capability ] )

源文本模块记录 module 的 ExecuteModule 具体方法接受可选参数 capability(一个 PromiseCapability Record),返回 包含 unused 的正常完成,或 抛出完成。调用时执行以下步骤:

  1. moduleContext 为一个新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 为 null
  3. moduleContextRealmmodule.[[Realm]]
  4. moduleContext 的 ScriptOrModule 为 module
  5. 断言module 已被链接,其模块环境中的声明已被实例化。
  6. moduleContext 的 VariableEnvironment 为 module.[[Environment]]
  7. moduleContext 的 LexicalEnvironment 为 module.[[Environment]]
  8. 暂停 运行的执行上下文
  9. 如果 module.[[HasTLA]]false,那么
    1. 断言capability 不存在。
    2. moduleContext 压入 执行上下文栈moduleContext 现在是 运行的执行上下文
    3. resultCompletion(module.[[ECMAScriptCode]]Evaluation)。
    4. 暂停 moduleContext 并从 执行上下文栈 中移除它。
    5. 恢复现在位于 执行上下文栈 顶部的上下文作为 运行的执行上下文
    6. 如果 result 是一个 异常完成,那么
      1. 返回 ? result
  10. 否则,
    1. 断言capability 是一个 PromiseCapability Record
    2. 执行 AsyncBlockStart(capability, module.[[ECMAScriptCode]], moduleContext)。
  11. 返回 unused

16.2.1.8 合成模块记录

合成模块记录用于表示由规范定义的模块的信息。其导出名称在创建时静态定义,而其对应的值可以通过 SetSyntheticModuleExport 随时间变化。它没有导入或依赖项。

合成模块记录可用于定义各种模块类型:例如,JSON 模块或 CSS 模块。

除了 表 43 中定义的字段外,合成模块记录还具有 表 62 中列出的附加字段。

表 62:合成模块记录的附加字段
字段名称 值类型 含义
[[ExportNames]] 字符串的 列表 模块的导出名称。此列表不包含重复项。
[[EvaluationSteps]] 一个 抽象闭包 在模块求值时执行的初始化逻辑,以 合成模块记录作为其唯一参数。它不得修改 [[ExportNames]]。它可能返回一个 异常完成

16.2.1.8.1 CreateDefaultExportSyntheticModule ( defaultExport )

抽象操作 CreateDefaultExportSyntheticModule 接受参数 defaultExport(一个 ECMAScript 语言值),返回一个 合成模块记录。它创建一个默认导出为 defaultExport合成模块记录。调用时执行以下步骤:

  1. realm当前 Realm Record
  2. setDefaultExport 为一个新的 抽象闭包,参数为 (module),捕获 defaultExport 并在调用时执行以下步骤:
    1. 执行 SetSyntheticModuleExport(module, "default", defaultExport)。
    2. 返回 NormalCompletion(unused)。
  3. 返回 合成模块记录 { [[Realm]]: realm, [[Environment]]: empty, [[Namespace]]: empty, [[HostDefined]]: undefined, [[ExportNames]]: « "default" », [[EvaluationSteps]]: setDefaultExport }。

16.2.1.8.2 ParseJSONModule ( source )

抽象操作 ParseJSONModule 接受参数 source(一个字符串),返回 包含一个 合成模块记录的正常完成,或 抛出完成。调用时执行以下步骤:

  1. json 为 ? ParseJSON(source)。
  2. 返回 CreateDefaultExportSyntheticModule(json)。

16.2.1.8.3 SetSyntheticModuleExport ( module, exportName, exportValue )

抽象操作 SetSyntheticModuleExport 接受参数 module(一个 合成模块记录)、exportName(一个字符串)和 exportValue(一个 ECMAScript 语言值),返回 unused。它可用于设置或更改 合成模块记录现有导出的导出值。调用时执行以下步骤:

  1. 断言module.[[ExportNames]] 包含 exportName
  2. envRecmodule.[[Environment]]
  3. 断言envRec 不是 empty
  4. 执行 envRec.SetMutableBinding(exportName, exportValue, true)。
  5. 返回 unused

16.2.1.8.4 模块记录抽象方法的实现

以下是 合成模块记录的具体方法,实现了 表 44 中定义的相应 模块记录抽象方法。

16.2.1.8.4.1 LoadRequestedModules ( )

合成模块记录 module 的 LoadRequestedModules 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:

  1. 返回 ! PromiseResolve(%Promise%, undefined)。
合成模块记录没有依赖项。

16.2.1.8.4.2 GetExportedNames ( )

合成模块记录 module 的 GetExportedNames 具体方法不接受参数,返回一个包含字符串的 列表。调用时执行以下步骤:

  1. 返回 module.[[ExportNames]]

16.2.1.8.4.3 ResolveExport ( exportName )

合成模块记录 module 的 ResolveExport 具体方法接受参数 exportName(一个字符串),返回一个 ResolvedBinding Recordnull。调用时执行以下步骤:

  1. 如果 module.[[ExportNames]] 不包含 exportName,返回 null
  2. 返回 ResolvedBinding Record { [[Module]]: module, [[BindingName]]: exportName }。

16.2.1.8.4.4 Link ( )

合成模块记录 module 的 Link 具体方法不接受参数,返回 包含 unused 的正常完成。调用时执行以下步骤:

  1. realmmodule.[[Realm]]
  2. envNewModuleEnvironment(realm.[[GlobalEnv]])。
  3. module.[[Environment]]env
  4. 对于 module.[[ExportNames]] 的每个字符串 exportName,执行
    1. 执行 ! env.CreateMutableBinding(exportName, false)。
    2. 执行 ! env.InitializeBinding(exportName, undefined)。
  5. 返回 NormalCompletion(unused)。

16.2.1.8.4.5 Evaluate ( )

合成模块记录 module 的 Evaluate 具体方法不接受参数,返回一个 Promise。调用时执行以下步骤:

  1. moduleContext 为一个新的 ECMAScript 代码执行上下文
  2. moduleContext 的 Function 为 null
  3. moduleContextRealmmodule.[[Realm]]
  4. moduleContext 的 ScriptOrModule 为 module
  5. moduleContext 的 VariableEnvironment 为 module.[[Environment]]
  6. moduleContext 的 LexicalEnvironment 为 module.[[Environment]]
  7. 暂停 运行的执行上下文
  8. moduleContext 压入 执行上下文栈moduleContext 现在是 运行的执行上下文
  9. stepsmodule.[[EvaluationSteps]]
  10. resultCompletion(steps(module))。
  11. 暂停 moduleContext 并从 执行上下文栈 中移除它。
  12. 恢复现在位于 执行上下文栈 顶部的上下文作为 运行的执行上下文
  13. pc 为 ! NewPromiseCapability(%Promise%)。
  14. IfAbruptRejectPromise(result, pc)。
  15. 执行 ! Call(pc.[[Resolve]], undefined, « undefined »)。
  16. 返回 pc.[[Promise]]

16.2.1.9 GetImportedModule ( referrer, request )

抽象操作 GetImportedModule 接受参数 referrer(一个 循环模块记录)和 request(一个 ModuleRequest Record),返回一个 模块记录。调用时执行以下步骤:

  1. records 为一个 列表,由 referrer.[[LoadedModules]] 中满足 ModuleRequestsEqual(r, request) 为 true 的每个 LoadedModuleRequest Record r 组成。
  2. 断言records 恰好有一个元素,因为在调用此抽象操作之前,LoadRequestedModules 已在 referrer 上成功完成。
  3. recordrecords 的唯一元素。
  4. 返回 record.[[Module]]

16.2.1.10 HostLoadImportedModule ( referrer, moduleRequest, hostDefined, payload )

宿主定义的抽象操作 HostLoadImportedModule 接受参数 referrer(一个 脚本记录、一个 循环模块记录或一个 Realm Record)、moduleRequest(一个 ModuleRequest Record)、hostDefined(任何值)和 payload(一个 GraphLoadingState Record 或一个 PromiseCapability Record),返回 unused

注 1

referrer 可以是 Realm Record 的一个例子是在 Web 浏览器 宿主中。在那里,如果用户点击由以下代码给出的控件

<button type="button" onclick="import('./foo.mjs')">Click me</button>

import() 表达式运行时,将没有 活动脚本或模块。更一般地,这可能发生在 宿主将具有 null ScriptOrModule 组件的 执行上下文推入 执行上下文栈的任何情况下。

HostLoadImportedModule 的实现必须符合以下要求:

执行的实际过程是 宿主定义的,但通常包括执行加载适当的 模块记录所需的任何 I/O 操作。多个不同的 (referrer, moduleRequest.[[Specifier]], moduleRequest.[[Attributes]]) 三元组可能映射到同一个 模块记录实例。实际的映射语义是 宿主定义的,但通常作为映射过程的一部分,会对 specifier 应用规范化过程。典型的规范化过程包括扩展相对和缩写路径说明符等操作。

注 2

上述文本要求 宿主在使用 type: "json" 导入时支持 JSON 模块(并且 HostLoadImportedModule 正常完成),但它不禁止 宿主在不使用 type: "json" 导入时支持 JSON 模块。

16.2.1.11 FinishLoadingImportedModule ( referrer, moduleRequest, payload, result )

抽象操作 FinishLoadingImportedModule 接受参数 referrer(一个 脚本记录、一个 循环模块记录或一个 Realm Record)、moduleRequest(一个 ModuleRequest Record)、payload(一个 GraphLoadingState Record 或一个 PromiseCapability Record)和 result包含一个 模块记录的正常完成或 抛出完成),返回 unused。调用时执行以下步骤:

  1. 如果 result正常完成,那么
    1. 如果 referrer.[[LoadedModules]] 包含一个 LoadedModuleRequest Record record,使得 ModuleRequestsEqual(record, moduleRequest) 为 true,那么
      1. 断言record.[[Module]]result.[[Value]] 是同一个 模块记录
    2. 否则,
      1. LoadedModuleRequest Record { [[Specifier]]: moduleRequest.[[Specifier]], [[Attributes]]: moduleRequest.[[Attributes]], [[Module]]: result.[[Value]] } 附加到 referrer.[[LoadedModules]]
  2. 如果 payloadGraphLoadingState Record,那么
    1. 执行 ContinueModuleLoading(payload, result)。
  3. 否则,
    1. 执行 ContinueDynamicImport(payload, result)。
  4. 返回 unused

16.2.1.12 AllImportAttributesSupported ( attributes )

抽象操作 AllImportAttributesSupported 接受参数 attributes(一个包含 ImportAttribute Records列表),返回一个布尔值。调用时执行以下步骤:

  1. supportedHostGetSupportedImportAttributes()。
  2. 对于 attributes 的每个 ImportAttribute Record attribute,执行
    1. 如果 supported 不包含 attribute.[[Key]],返回 false
  3. 返回 true

16.2.1.12.1 HostGetSupportedImportAttributes ( )

宿主定义的抽象操作 HostGetSupportedImportAttributes 不接受参数,返回一个包含字符串的 列表。它允许 宿主环境指定它们支持的导入属性。只有具有受支持键的属性才会提供给 宿主

HostGetSupportedImportAttributes 的实现必须符合以下要求:

  • 它必须返回一个包含字符串的 列表,每个字符串表示一个受支持的属性。
  • 每次调用此操作时,它必须返回相同的 列表,包含相同顺序的相同内容。

HostGetSupportedImportAttributes 的默认实现是返回一个新的空 列表

要求 宿主指定其受支持的导入属性,而不是将所有属性传递给 宿主并让其选择要处理哪些属性的目的,是确保不受支持的属性在不同 宿主之间以一致的方式处理。

16.2.1.13 GetModuleNamespace ( module )

抽象操作 GetModuleNamespace 接受参数 module模块记录具体子类的实例),返回一个模块命名空间对象。它检索表示 module 导出的模块命名空间对象,在第一次请求时惰性创建它,并将其存储在 module.[[Namespace]] 中以供将来检索。调用时执行以下步骤:

  1. 断言:如果 module循环模块记录,那么 module.[[Status]] 不是 newunlinked
  2. namespacemodule.[[Namespace]]
  3. 如果 namespaceempty,那么
    1. exportedNamesmodule.GetExportedNames()。
    2. unambiguousNames 为一个新的空 列表
    3. 对于 exportedNames 的每个元素 name,执行
      1. resolutionmodule.ResolveExport(name)。
      2. 如果 resolutionResolvedBinding Record,将 name 附加到 unambiguousNames
    4. namespaceModuleNamespaceCreate(module, unambiguousNames)。
  4. 返回 namespace

GetModuleNamespace 永远不会抛出异常。相反,无法解析的名称在此时简单地从命名空间中排除。除非它们都是未在任何地方明确请求的歧义星号导出,否则稍后会导致真正的链接错误。

16.2.1.14 运行时语义:求值

Module : [empty]
  1. 返回 undefined
ModuleBody : ModuleItemList
  1. resultCompletion(ModuleItemList求值)。
  2. 如果 result正常完成result.[[Value]]empty,那么
    1. 返回 undefined
  3. 返回 ? result
ModuleItemList : ModuleItemList ModuleItem
  1. sl 为 ? ModuleItemList求值
  2. sCompletion(ModuleItem求值)。
  3. 返回 ? UpdateEmpty(s, sl)。

ModuleItemList 的值是 ModuleItemList 中最后一个产生值的项的值。

ModuleItem : ImportDeclaration
  1. 返回 empty

16.2.2 导入

语法

ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral

16.2.2.1 静态语义:早期错误

ModuleItem : ImportDeclaration WithClause : with { WithEntries ,opt }

16.2.2.2 静态语义:ImportEntries

语法导向操作 ImportEntries 不接受参数,返回一个包含 ImportEntry Records列表。它在以下产生式上分段定义:

Module : [empty]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListImportEntries
  2. entries2ModuleItemImportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ExportDeclaration StatementListItem
  1. 返回一个新的空 列表
ImportDeclaration : import ImportClause FromClause WithClauseopt ;
  1. moduleImportDeclarationModuleRequests 的唯一元素。
  2. 返回 ImportClause 以参数 moduleImportEntriesForModule
ImportDeclaration : import ModuleSpecifier WithClauseopt ;
  1. 返回一个新的空 列表

16.2.2.3 静态语义:ImportEntriesForModule

语法导向操作 ImportEntriesForModule 接受参数 module(一个 ModuleRequest Record),返回一个包含 ImportEntry Records列表。它在以下产生式上分段定义:

ImportClause : ImportedDefaultBinding , NameSpaceImport
  1. entries1ImportedDefaultBinding 以参数 moduleImportEntriesForModule
  2. entries2NameSpaceImport 以参数 moduleImportEntriesForModule
  3. 返回 entries1entries2列表连接
ImportClause : ImportedDefaultBinding , NamedImports
  1. entries1ImportedDefaultBinding 以参数 moduleImportEntriesForModule
  2. entries2NamedImports 以参数 moduleImportEntriesForModule
  3. 返回 entries1entries2列表连接
ImportedDefaultBinding : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. defaultEntryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: "default", [[LocalName]]: localName }。
  3. 返回 « defaultEntry »。
NameSpaceImport : * as ImportedBinding
  1. localNameImportedBindingStringValue
  2. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: namespace-object, [[LocalName]]: localName }。
  3. 返回 « entry »。
NamedImports : { }
  1. 返回一个新的空 列表
ImportsList : ImportsList , ImportSpecifier
  1. specs1ImportsList 以参数 moduleImportEntriesForModule
  2. specs2ImportSpecifier 以参数 moduleImportEntriesForModule
  3. 返回 specs1specs2列表连接
ImportSpecifier : ImportedBinding
  1. localNameImportedBindingBoundNames 的唯一元素。
  2. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: localName, [[LocalName]]: localName }。
  3. 返回 « entry »。
ImportSpecifier : ModuleExportName as ImportedBinding
  1. importNameModuleExportNameStringValue
  2. localNameImportedBindingStringValue
  3. entryImportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName }。
  4. 返回 « entry »。

16.2.2.4 静态语义:WithClauseToAttributes

语法导向操作 WithClauseToAttributes 不接受参数,返回一个包含 ImportAttribute Records列表。它在以下产生式上分段定义:

WithClause : with { }
  1. 返回一个新的空 列表
WithClause : with { WithEntries ,opt }
  1. attributesWithEntriesWithClauseToAttributes
  2. 根据 attributes[[Key]] 字段的字典序对其进行排序,将每个这样的字段值视为 UTF-16 代码单元值的序列。注:此排序仅在禁止 宿主根据属性枚举的顺序改变行为时可观察到。
  3. 返回 attributes
WithEntries : AttributeKey : StringLiteral
  1. keyAttributeKeyPropName
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. 返回 « entry »。
WithEntries : AttributeKey : StringLiteral , WithEntries
  1. keyAttributeKeyPropName
  2. entryImportAttribute Record { [[Key]]: key, [[Value]]: StringLiteralSV }。
  3. restWithEntriesWithClauseToAttributes
  4. 返回 « entry » 和 rest列表连接

16.2.3 导出

语法

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

16.2.3.1 静态语义:早期错误

ExportDeclaration : export NamedExports ;

上述规则意味着 NamedExports 的每个 ReferencedBindings 都被视为 IdentifierReference

16.2.3.2 静态语义:ExportedBindings

语法导向操作 ExportedBindings 不接受参数,返回一个字符串 列表

ExportedBindings 是与 ModuleExportedNames 明确关联的本地绑定名称。

它在以下产生式上分段定义:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedBindings
  2. names2ModuleItemExportedBindings
  3. 返回 names1names2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回一个新的空 列表
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExportsExportedBindings
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回此 ExportDeclarationBoundNames
NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedBindings
  2. names2ExportSpecifierExportedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 列表,其唯一元素是 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 列表,其唯一元素是第一个 ModuleExportNameStringValue

16.2.3.3 静态语义:ExportedNames

语法导向操作 ExportedNames 不接受参数,返回一个字符串 列表

ExportedNames 是 Module 明确映射到其本地名称绑定之一的外部可见名称。

它在以下产生式上分段定义:

ModuleItemList : ModuleItemList ModuleItem
  1. names1ModuleItemListExportedNames
  2. names2ModuleItemExportedNames
  3. 返回 names1names2列表连接
ModuleItem : ExportDeclaration
  1. 返回 ExportDeclarationExportedNames
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. 返回 ExportFromClauseExportedNames
ExportFromClause : *
  1. 返回一个新的空 列表
ExportFromClause : * as ModuleExportName
  1. 返回一个 列表,其唯一元素是 ModuleExportNameStringValue
ExportFromClause : NamedExports
  1. 返回 NamedExportsExportedNames
ExportDeclaration : export VariableStatement
  1. 返回 VariableStatementBoundNames
ExportDeclaration : export Declaration
  1. 返回 DeclarationBoundNames
ExportDeclaration : export default HoistableDeclaration export default ClassDeclaration export default AssignmentExpression ;
  1. 返回 « "default" »。
NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListExportedNames
  2. names2ExportSpecifierExportedNames
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName
  1. 返回一个 列表,其唯一元素是 ModuleExportNameStringValue
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回一个 列表,其唯一元素是第二个 ModuleExportNameStringValue

16.2.3.4 静态语义:ExportEntries

语法导向操作 ExportEntries 不接受参数,返回一个包含 ExportEntry Records列表。它在以下产生式上分段定义:

Module : [empty]
  1. 返回一个新的空 列表
ModuleItemList : ModuleItemList ModuleItem
  1. entries1ModuleItemListExportEntries
  2. entries2ModuleItemExportEntries
  3. 返回 entries1entries2列表连接
ModuleItem : ImportDeclaration StatementListItem
  1. 返回一个新的空 列表
ExportDeclaration : export ExportFromClause FromClause WithClauseopt ;
  1. moduleExportDeclarationModuleRequests 的唯一元素。
  2. 返回 ExportFromClause 以参数 moduleExportEntriesForModule
ExportDeclaration : export NamedExports ;
  1. 返回 NamedExports 以参数 nullExportEntriesForModule
ExportDeclaration : export VariableStatement
  1. entries 为一个新的空 列表
  2. namesVariableStatementBoundNames
  3. 对于 names 的每个元素 name,执行
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export Declaration
  1. entries 为一个新的空 列表
  2. namesDeclarationBoundNames
  3. 对于 names 的每个元素 name,执行
    1. ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: name, [[ExportName]]: name } 追加到 entries
  4. 返回 entries
ExportDeclaration : export default HoistableDeclaration
  1. namesHoistableDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default ClassDeclaration
  1. namesClassDeclarationBoundNames
  2. localNamenames 的唯一元素。
  3. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: localName, [[ExportName]]: "default" }。
ExportDeclaration : export default AssignmentExpression ;
  1. entryExportEntry Record { [[ModuleRequest]]: null, [[ImportName]]: null, [[LocalName]]: "*default*", [[ExportName]]: "default" }。
  2. 返回 « entry »。

"*default*" 在本规范中用作匿名默认导出值的合成名称。详见 此注释

16.2.3.5 静态语义:ExportEntriesForModule

语法导向操作 ExportEntriesForModule 接受参数 module(一个 ModuleRequest Recordnull)并返回一个包含 ExportEntry Records列表。它在以下产生式上分段定义:

ExportFromClause : *
  1. entryExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all-but-default, [[LocalName]]: null, [[ExportName]]: null }。
  2. 返回 « entry »。
ExportFromClause : * as ModuleExportName
  1. exportNameModuleExportNameStringValue
  2. entryExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: all, [[LocalName]]: null, [[ExportName]]: exportName }。
  3. 返回 « entry »。
NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. specs1ExportsList 以参数 moduleExportEntriesForModule
  2. specs2ExportSpecifier 以参数 moduleExportEntriesForModule
  3. 返回 specs1specs2列表连接
ExportSpecifier : ModuleExportName
  1. sourceNameModuleExportNameStringValue
  2. 如果 modulenull,那么
    1. localNamesourceName
    2. importNamenull
  3. 否则,
    1. localNamenull
    2. importNamesourceName
  4. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: sourceName }。
ExportSpecifier : ModuleExportName as ModuleExportName
  1. sourceName 为第一个 ModuleExportNameStringValue
  2. exportName 为第二个 ModuleExportNameStringValue
  3. 如果 modulenull,那么
    1. localNamesourceName
    2. importNamenull
  4. 否则,
    1. localNamenull
    2. importNamesourceName
  5. 返回一个 列表,其唯一元素是一个新的 ExportEntry Record { [[ModuleRequest]]: module, [[ImportName]]: importName, [[LocalName]]: localName, [[ExportName]]: exportName }。

16.2.3.6 静态语义:ReferencedBindings

语法导向操作 ReferencedBindings 不接受参数,返回一个包含 解析节点列表。它在以下产生式上分段定义:

NamedExports : { }
  1. 返回一个新的空 列表
ExportsList : ExportsList , ExportSpecifier
  1. names1ExportsListReferencedBindings
  2. names2ExportSpecifierReferencedBindings
  3. 返回 names1names2列表连接
ExportSpecifier : ModuleExportName as ModuleExportName
  1. 返回第一个 ModuleExportNameReferencedBindings
ModuleExportName : IdentifierName
  1. 返回一个 列表,其唯一元素是 IdentifierName
ModuleExportName : StringLiteral
  1. 返回一个 列表,其唯一元素是 StringLiteral

16.2.3.7 运行时语义:Evaluation

ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ;
  1. 返回 empty
ExportDeclaration : export VariableStatement
  1. 返回 ? VariableStatementEvaluation
ExportDeclaration : export Declaration
  1. 返回 ? DeclarationEvaluation
ExportDeclaration : export default HoistableDeclaration
  1. 返回 ? HoistableDeclarationEvaluation
ExportDeclaration : export default ClassDeclaration
  1. value 为 ? ClassDeclarationBindingClassDeclarationEvaluation
  2. classNameClassDeclarationBoundNames 的唯一元素。
  3. 如果 className"*default*",那么
    1. env正在运行的执行上下文 的 LexicalEnvironment。
    2. 执行 ? InitializeBoundName("*default*", value, env)。
  4. 返回 empty
ExportDeclaration : export default AssignmentExpression ;
  1. 如果 IsAnonymousFunctionDefinition(AssignmentExpression) 是 true,那么
    1. value 为 ? AssignmentExpression 以参数 "default"NamedEvaluation
  2. 否则,
    1. rhs 为 ? AssignmentExpressionEvaluation
    2. value 为 ? GetValue(rhs)。
  3. env正在运行的执行上下文 的 LexicalEnvironment。
  4. 执行 ? InitializeBoundName("*default*", value, env)。
  5. 返回 empty

17 错误处理和语言扩展

实现必须在评估相关的 ECMAScript 语言结构时报告大部分错误。早期错误是可以在评估包含错误的 Script 中的任何结构之前检测和报告的错误。早期错误的存在会阻止结构的评估。实现必须在 ParseScript 中解析 Script 时报告 Script 中的 早期错误Module 中的 早期错误Module 将要被评估的时候报告,并且 Module 永远不会被初始化。eval 代码中的 早期错误在调用 eval 时报告,并阻止 eval 代码的评估。所有不是 早期错误的错误都是运行时错误。

实现必须将本规范的"静态语义:早期错误"子条款中列出的任何条件的出现报告为 早期错误

即使编译器可以证明结构在任何情况下都不能无错误地执行,实现也不应将其他类型的错误视为 早期错误。实现可以在这种情况下发出早期警告,但它不应该在相关结构实际执行之前报告错误。

实现应按规定报告所有错误,除了以下情况:

17.1 禁止的扩展

实现不得以以下方式扩展本规范:

18 ECMAScript 标准内置对象

每当 ECMAScript ScriptModule 开始执行时,都有某些内置对象可用。其中,全局对象是执行程序的全局环境的一部分。其他对象可以作为 全局对象的初始属性访问,或者作为可访问的内置对象的属性间接访问。

除非另有规定,可作为函数调用的内置对象是内置 函数对象,具有 10.3 中描述的特性。除非另有规定,内置对象的 [[Extensible]] 内部插槽最初具有值 true。每个内置 函数对象都有一个 [[Realm]] 内部插槽,其值是对象最初为其创建的 境界Realm Record

许多内置对象都是函数:它们可以用参数调用。其中一些还是 构造器:它们是用于与 new 操作符一起使用的函数。对于每个内置函数,本规范描述了该函数所需的参数和该 函数对象的属性。对于每个内置 构造器,本规范还描述了该 构造器的原型对象的属性以及调用该 构造器new 表达式返回的特定对象实例的属性。

除非在特定函数的描述中另有规定,如果内置函数或 构造器给定的参数少于函数指定要求的参数,该函数或 构造器的行为应完全如同已给定了足够的附加参数,每个这样的参数都是 undefined 值。这样的缺失参数被认为是"不存在的",并且可以通过规范算法以这种方式识别。在特定函数的描述中,术语"this 值"和"NewTarget"具有 10.3 中给出的含义。

除非在特定函数的描述中另有规定,如果所描述的内置函数或 构造器给定的参数比函数指定允许的更多,则额外的参数由调用评估然后被函数忽略。但是,实现可以定义与这些参数相关的实现特定行为,只要该行为不是简单基于额外参数存在而抛出 TypeError 异常。

注 1

鼓励向内置函数集添加附加功能的实现通过添加新函数而不是向现有函数添加新参数来实现。

除非另有规定,每个内置函数和每个内置 构造器都将 Function 原型对象作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Function.prototype20.2.3)的初始值。

除非另有规定,每个内置原型对象都将 Object 原型对象作为其 [[Prototype]] 内部插槽的值,该对象是表达式 Object.prototype20.1.3)的初始值,除了 Object 原型对象本身。

如果本规范通过算法步骤定义内置 构造器的行为,那么这就是它在 [[Call]][[Construct]] 目的上的行为。如果这样的算法需要区分这两种情况,它会检查 NewTarget 是否为 undefined,这表示 [[Call]] 调用。

未被标识为 构造器的内置 函数对象不实现 [[Construct]] 内部方法,除非在特定函数的描述中另有规定。

不是 构造器的内置 函数对象没有 "prototype" 属性,除非在特定函数的描述中另有规定。

本规范中定义的每个内置函数都是通过调用 CreateBuiltinFunction 抽象操作(10.3.4)创建的。lengthname 参数的值是 "length""name" 属性的初始值,如下所述。prefix 参数的值也在下面类似地讨论。

每个内置 函数对象,包括 构造器,都有一个 "length" 属性,其值是非负的 整数。除非另有规定,此值是函数描述的子条款标题中显示的必需参数数。可选参数和剩余参数不包括在参数计数中。

注 2

例如,Array 原型对象"map" 属性的初始值的 函数对象在子条款标题"Array.prototype.map (callback [ , thisArg])"下描述,显示了两个命名参数 callback 和 thisArg,后者是可选的;因此该 函数对象"length" 属性的值是 1𝔽

除非另有规定,内置 函数对象"length" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

每个内置 函数对象,包括 构造器,都有一个 "name" 属性,其值 是一个字符串。除非另有规定,此值是本规范中给予函数的名称。被标识为匿名函数的函数使用空字符串作为 "name" 属性的值。对于被指定为对象属性的函数,名称值是用于访问函数的 属性名字符串。被指定为内置属性的 get 或 set 访问器函数的函数在调用 CreateBuiltinFunction 时将 "get""set"(分别)传递给 prefix 参数。

对于 属性键 是 Symbol 值的每个内置函数,"name" 属性的值被显式指定。如果这样的显式指定值以前缀 "get ""set " 开头,并且为其指定的函数是内置属性的 get 或 set 访问器函数,则不带前缀的值传递给 name 参数,并且值 "get""set"(分别)在调用 CreateBuiltinFunction 时传递给 prefix 参数。

除非另有规定,内置 函数对象"name" 属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

条款 1928 以及附录 B.2 中描述的每个其他 数据属性都具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true },除非另有规定。

条款 1928 以及附录 B.2 中描述的每个 访问器属性都具有特性 { [[Enumerable]]: false, [[Configurable]]: true },除非另有规定。如果只描述了 get 访问器函数,则 set 访问器函数是默认值 undefined。如果只描述了 set 访问器,则 get 访问器是默认值 undefined

19 全局对象

全局对象

19.1 全局对象的值属性

19.1.1 globalThis

Realm Record realm全局对象"globalThis" 属性的初始值是 realm.[[GlobalEnv]].[[GlobalThisValue]]

此属性具有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: true }。

19.1.2 Infinity

Infinity 的值是 +∞𝔽(见 6.1.6.1)。此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.3 NaN

NaN 的值是 NaN(见 6.1.6.1)。此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.1.4 undefined

undefined 的值是 undefined(见 6.1.1)。此属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

19.2 全局对象的函数属性

19.2.1 eval ( x )

此函数是 %eval% 内置对象。

当被调用时执行以下步骤:

  1. 返回 ? PerformEval(x, false, false)。

19.2.1.1 PerformEval ( x, strictCaller, direct )

抽象操作 PerformEval 接受参数 x(一个 ECMAScript 语言值)、strictCaller(一个布尔值)和 direct(一个布尔值),返回一个包含 ECMAScript 语言值正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 断言:如果 directfalse,那么 strictCaller 也是 false
  2. 如果 x 不是字符串,返回 x
  3. evalRealm当前 Realm Record
  4. 注:在 直接 eval 的情况下,evalRealmeval 调用者和 eval 函数本身的 境界
  5. 执行 ? HostEnsureCanCompileStrings(evalRealm, « », x, direct)。
  6. inFunctionfalse
  7. inMethodfalse
  8. inDerivedConstructorfalse
  9. inClassFieldInitializerfalse
  10. 如果 directtrue,那么
    1. thisEnvRecGetThisEnvironment()。
    2. 如果 thisEnvRec 是一个 函数环境记录,那么
      1. FthisEnvRec.[[FunctionObject]]
      2. inFunctiontrue
      3. inMethodthisEnvRec.HasSuperBinding()。
      4. 如果 F.[[ConstructorKind]]derived,设 inDerivedConstructortrue
      5. classFieldInitializerNameF.[[ClassFieldInitializerName]]
      6. 如果 classFieldInitializerName 不是 empty,设 inClassFieldInitializertrue
  11. 实现定义的顺序执行以下子步骤,可能交替进行解析和错误检测:
    1. scriptParseText(x, Script)。
    2. 如果 script 是一个错误的 列表,抛出 SyntaxError 异常。
    3. 如果 script Contains ScriptBodyfalse,返回 undefined
    4. bodyscriptScriptBody
    5. 如果 inFunctionfalsebody Contains NewTarget, 抛出 SyntaxError 异常。
    6. 如果 inMethodfalsebody Contains SuperProperty,抛出 SyntaxError 异常。
    7. 如果 inDerivedConstructorfalsebody Contains SuperCall, 抛出 SyntaxError 异常。
    8. 如果 inClassFieldInitializertruebodyContainsArgumentstrue,抛出 SyntaxError 异常。
  12. 如果 strictCallertrue,设 strictEvaltrue
  13. 否则,设 strictEvalscriptScriptIsStrict
  14. runningContext正在运行的执行上下文
  15. 注:如果 directtruerunningContext 将是执行 直接 eval执行上下文。如果 directfalserunningContext 将是调用 eval 函数的 执行上下文
  16. 如果 directtrue,那么
    1. lexEnvNewDeclarativeEnvironment(runningContext 的 LexicalEnvironment)。
    2. varEnvrunningContext 的 VariableEnvironment。
    3. privateEnvrunningContext 的 PrivateEnvironment。
  17. 否则,
    1. lexEnvNewDeclarativeEnvironment(evalRealm.[[GlobalEnv]])。
    2. varEnvevalRealm.[[GlobalEnv]]
    3. privateEnvnull
  18. 如果 strictEvaltrue,设 varEnvlexEnv
  19. 如果 runningContext 尚未挂起,挂起 runningContext
  20. evalContext 为一个新的 ECMAScript 代码执行上下文
  21. evalContext 的 Function 为 null
  22. evalContextRealmevalRealm
  23. evalContext 的 ScriptOrModule 为 runningContext 的 ScriptOrModule。
  24. evalContext 的 VariableEnvironment 为 varEnv
  25. evalContext 的 LexicalEnvironment 为 lexEnv
  26. evalContext 的 PrivateEnvironment 为 privateEnv
  27. evalContext 推入 执行上下文栈evalContext 现在是 正在运行的执行上下文
  28. resultCompletion(EvalDeclarationInstantiation(body, varEnv, lexEnv, privateEnv, strictEval))。
  29. 如果 result 是一个 正常完成,那么
    1. resultCompletion(bodyEvaluation)。
  30. 如果 result 是一个 正常完成result.[[Value]]empty,那么
    1. resultNormalCompletion(undefined)。
  31. 挂起 evalContext 并将其从 执行上下文栈中移除。
  32. 恢复现在位于 执行上下文栈顶部的上下文作为 正在运行的执行上下文
  33. 返回 ? result

如果调用上下文的代码或 eval 代码是 严格模式代码,那么 eval 代码不能在调用 eval 的调用上下文的变量环境中实例化变量或函数绑定。相反,这些绑定在只有 eval 代码可访问的新 VariableEnvironment 中实例化。由 letconstclass 声明引入的绑定总是在新的 LexicalEnvironment 中实例化。

19.2.1.2 HostEnsureCanCompileStrings ( calleeRealm, parameterStrings, bodyString, direct )

宿主定义的抽象操作 HostEnsureCanCompileStrings 接受参数 calleeRealm(一个 Realm Record)、parameterStrings(一个字符串的 列表)、bodyString(一个字符串)和 direct(一个布尔值),返回一个包含 unused正常完成或一个 抛出完成。它允许 宿主环境阻止某些允许开发者将字符串解释和评估为 ECMAScript 代码的 ECMAScript 函数。

parameterStrings 表示在使用函数 构造器之一时将连接在一起以构建参数列表的字符串。bodyString 表示函数体或传递给 eval 调用的字符串。direct 表示评估是否是 直接 eval

HostEnsureCanCompileStrings 的默认实现是返回 NormalCompletion(unused)。

19.2.1.3 EvalDeclarationInstantiation ( body, varEnv, lexEnv, privateEnv, strict )

抽象操作 EvalDeclarationInstantiation 接受参数 body(一个 ScriptBody 解析节点)、varEnv(一个 环境记录)、lexEnv(一个 声明式环境记录)、privateEnv(一个 私有环境记录null)和 strict(一个布尔值),返回一个包含 unused正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. varNamesbodyVarDeclaredNames
  2. varDeclarationsbodyVarScopedDeclarations
  3. 如果 strictfalse,那么
    1. 如果 varEnv 是一个 全局环境记录,那么
      1. 对于 varNames 的每个元素 name,执行
        1. 如果 HasLexicalDeclaration(varEnv, name) 是 true,抛出 SyntaxError 异常。
        2. 注:eval 不会创建被全局词法声明遮蔽的全局 var 声明。
    2. thisEnvlexEnv
    3. 断言:以下循环将终止。
    4. 重复,当 thisEnvvarEnv 不是同一个 环境记录时,
      1. 如果 thisEnv 不是对象 环境记录,那么
        1. 注:with 语句的环境不能包含任何词法声明,因此不需要检查 var/let 提升冲突。
        2. 对于 varNames 的每个元素 name,执行
          1. 如果 ! thisEnv.HasBinding(name) 是 true,那么
            1. 抛出 SyntaxError 异常。
            2. 注:附录 B.3.4 为上述步骤定义了替代语义。
          2. 注:直接 eval 不会将 var 声明提升到同名的词法声明之上。
      2. thisEnvthisEnv.[[OuterEnv]]
  4. privateIdentifiers 为一个新的空 列表
  5. pointerprivateEnv
  6. 重复,当 pointer 不是 null 时,
    1. 对于 pointer.[[Names]] 的每个 私有名称 binding,执行
      1. 如果 privateIdentifiers 不包含 binding.[[Description]],将 binding.[[Description]] 添加到 privateIdentifiers
    2. pointerpointer.[[OuterPrivateEnvironment]]
  7. 如果 body 以参数 privateIdentifiersAllPrivateIdentifiersValidfalse,抛出 SyntaxError 异常。
  8. functionsToInitialize 为一个新的空 列表
  9. declaredFunctionNames 为一个新的空 列表
  10. 对于 varDeclarations 的每个元素 d,以反向 列表顺序,执行
    1. 如果 d 不是 VariableDeclarationForBindingBindingIdentifier,那么
      1. 断言dFunctionDeclarationGeneratorDeclarationAsyncFunctionDeclarationAsyncGeneratorDeclaration
      2. 注:如果同一个名称有多个函数声明,使用最后一个声明。
      3. fndBoundNames 的唯一元素。
      4. 如果 declaredFunctionNames 不包含 fn,那么
        1. 如果 varEnv 是一个 全局环境记录,那么
          1. fnDefinable 为 ? CanDeclareGlobalFunction(varEnv, fn)。
          2. 如果 fnDefinablefalse,抛出 TypeError 异常。
        2. fn 添加到 declaredFunctionNames
        3. d 插入为 functionsToInitialize 的第一个元素。
  11. declaredVarNames 为一个新的空 列表
  12. 对于 varDeclarations 的每个元素 d,执行
    1. 如果 dVariableDeclarationForBindingBindingIdentifier,那么
      1. 对于 dBoundNames 的每个字符串 vn,执行
        1. 如果 declaredFunctionNames 不包含 vn,那么
          1. 如果 varEnv 是一个 全局环境记录,那么
            1. vnDefinable 为 ? CanDeclareGlobalVar(varEnv, vn)。
            2. 如果 vnDefinablefalse,抛出 TypeError 异常。
          2. 如果 declaredVarNames 不包含 vn,那么
            1. vn 添加到 declaredVarNames
  13. 注:附录 B.3.2.3 在此处添加额外的步骤。
  14. 注:除非 varEnv 是一个 全局环境记录全局对象是一个 Proxy 异质对象,否则在此算法步骤之后不会发生异常终止。
  15. lexDeclarationsbodyLexicallyScopedDeclarations
  16. 对于 lexDeclarations 的每个元素 d,执行
    1. 注:词法声明的名称仅在此处实例化但不初始化。
    2. 对于 dBoundNames 的每个元素 dn,执行
      1. 如果 dIsConstantDeclarationtrue,那么
        1. 执行 ? lexEnv.CreateImmutableBinding(dn, true)。
      2. 否则,
        1. 执行 ? lexEnv.CreateMutableBinding(dn, false)。
  17. 对于 functionsToInitialize 的每个 解析节点 f,执行
    1. fnfBoundNames 的唯一元素。
    2. fof 以参数 lexEnvprivateEnvInstantiateFunctionObject
    3. 如果 varEnv 是一个 全局环境记录,那么
      1. 执行 ? CreateGlobalFunctionBinding(varEnv, fn, fo, true)。
    4. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(fn)。
      2. 如果 bindingExistsfalse,那么
        1. 注:由于步骤 14 之前的验证,以下调用不能返回 异常完成
        2. 执行 ! varEnv.CreateMutableBinding(fn, true)。
        3. 执行 ! varEnv.InitializeBinding(fn, fo)。
      3. 否则,
        1. 执行 ! varEnv.SetMutableBinding(fn, fo, false)。
  18. 对于 declaredVarNames 的每个字符串 vn,执行
    1. 如果 varEnv 是一个 全局环境记录,那么
      1. 执行 ? CreateGlobalVarBinding(varEnv, vn, true)。
    2. 否则,
      1. bindingExists 为 ! varEnv.HasBinding(vn)。
      2. 如果 bindingExistsfalse,那么
        1. 注:由于步骤 14 之前的验证,以下调用不能返回 异常完成
        2. 执行 ! varEnv.CreateMutableBinding(vn, true)。
        3. 执行 ! varEnv.InitializeBinding(vn, undefined)。
  19. 返回 unused

此算法的替代版本在 B.3.4 中描述。

19.2.2 isFinite ( number )

此函数是 %isFinite% 内置对象。

当被调用时执行以下步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 num 不是 有限的,返回 false
  3. 否则,返回 true

19.2.3 isNaN ( number )

此函数是 %isNaN% 内置对象。

当被调用时执行以下步骤:

  1. num 为 ? ToNumber(number)。
  2. 如果 numNaN,返回 true
  3. 否则,返回 false

ECMAScript 代码测试值 X 是否为 NaN 的可靠方法是使用形式为 X !== X 的表达式。当且仅当 XNaN 时,结果将是 true

19.2.4 parseFloat ( string )

此函数根据对 string 参数内容作为十进制字面量的解释产生一个数值。

它是 %parseFloat% 内置对象。

当被调用时执行以下步骤:

  1. inputString 为 ? ToString(string)。
  2. trimmedString 为 ! TrimString(inputString, start)。
  3. trimmedStringToCodePoints(trimmedString)。
  4. trimmedPrefix 为满足 StrDecimalLiteral 语法的 trimmed 的最长前缀,可能是 trimmed 本身。如果没有这样的前缀,返回 NaN
  5. parsedNumberParseText(trimmedPrefix, StrDecimalLiteral)。
  6. 断言parsedNumber 是一个 解析节点
  7. 返回 parsedNumberStringNumericValue

此函数可能仅将 string 的前导部分解释为数值;它忽略任何不能解释为十进制字面量表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。

19.2.5 parseInt ( string, radix )

此函数根据指定的 radixstring 内容的解释产生一个 整数。忽略 string 中的前导空白。如果 radix 强制转换为 0(例如当它是 undefined 时),则假设为 10,除非数字表示以 "0x""0X" 开头,在这种情况下假设为 16。如果 radix 是 16,数字表示可以可选地以 "0x""0X" 开头。

它是 %parseInt% 内置对象。

当被调用时执行以下步骤:

  1. inputString 为 ? ToString(string)。
  2. S 为 ! TrimString(inputString, start)。
  3. sign 为 1。
  4. 如果 S 不为空且 S 的第一个代码单元是代码单元 0x002D(连字符减号),设 sign 为 -1。
  5. 如果 S 不为空且 S 的第一个代码单元是代码单元 0x002B(加号)或代码单元 0x002D(连字符减号),设 SS 从索引 1 开始的 子字符串
  6. R(? ToInt32(radix))。
  7. stripPrefixtrue
  8. 如果 R ≠ 0,那么
    1. 如果 R < 2 或 R > 36,返回 NaN
    2. 如果 R ≠ 16,设 stripPrefixfalse
  9. 否则,
    1. R 为 10。
  10. 如果 stripPrefixtrue,那么
    1. 如果 S 的长度至少为 2 且 S 的前两个代码单元是 "0x""0X",那么
      1. SS 从索引 2 开始的 子字符串
      2. R 为 16。
  11. 如果 S 包含不是基数-R 数字的代码单元,设 endS 中第一个这样的代码单元的索引;否则,设 endS 的长度。
  12. ZS 从 0 到 end子字符串
  13. 如果 Z 为空,返回 NaN
  14. mathInt 为以基数-R 表示法表示的 Z 所表示的 整数值,使用字母 AZaz 表示值 10 到 35 的数字。(但是,如果 R = 10 且 Z 包含超过 20 个有效数字,实现可以选择将第 20 个之后的每个有效数字替换为 0 数字;如果 R 不是 2、4、8、10、16 或 32 之一,那么 mathInt 可能是一个 实现近似的 整数,表示 Z 在基数-R 表示法中表示的 整数值。)
  15. 如果 mathInt = 0,那么
    1. 如果 sign = -1,返回 -0𝔽
    2. 返回 +0𝔽
  16. 返回 𝔽(sign × mathInt)。

此函数可能仅将 string 的前导部分解释为 整数值;它忽略任何不能解释为 整数表示法一部分的代码单元,并且不会给出任何此类代码单元被忽略的指示。

19.2.6 URI 处理函数

统一资源标识符(URI)是标识资源(例如网页或文件)和访问它们的传输协议(例如 HTTP 或 FTP)的字符串。ECMAScript 语言本身不提供对使用 URI 的任何支持,除了本节中描述的编码和解码 URI 的函数。encodeURIdecodeURI 旨在与完整的 URI 一起工作;它们假设任何保留字符都旨在具有特殊含义(例如,作为分隔符),因此不进行编码。encodeURIComponentdecodeURIComponent 旨在与 URI 的各个组件一起工作;它们假设任何保留字符表示文本,必须编码以避免在组件是完整 URI 的一部分时具有特殊含义。

注 1

保留字符集基于 RFC 2396,不反映更新的 RFC 3986 引入的更改。

注 2

许多 ECMAScript 实现提供操作网页的附加函数和方法;这些函数超出了本标准的范围。

19.2.6.1 decodeURI ( encodedURI )

此函数计算 URI 的新版本,其中每个可能由 encodeURI 函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16 编码替换。不可能由 encodeURI 引入的转义序列不被替换。

它是 %decodeURI% 内置对象。

当被调用时执行以下步骤:

  1. uriString 为 ? ToString(encodedURI)。
  2. preserveEscapeSet";/?:@&=+$,#"
  3. 返回 ? Decode(uriString, preserveEscapeSet)。

19.2.6.2 decodeURIComponent ( encodedURIComponent )

此函数计算 URI 的新版本,其中每个可能由 encodeURIComponent 函数引入的转义序列和 UTF-8 编码都被其表示的代码点的 UTF-16 编码替换。

它是 %decodeURIComponent% 内置对象。

当被调用时执行以下步骤:

  1. componentString 为 ? ToString(encodedURIComponent)。
  2. preserveEscapeSet 为空字符串。
  3. 返回 ? Decode(componentString, preserveEscapeSet)。

19.2.6.3 encodeURI ( uri )

此函数计算 UTF-16 编码(6.1.4)URI 的新版本,其中某些代码点的每个实例都被表示代码点的 UTF-8 编码的一个、两个、三个或四个转义序列替换。

它是 %encodeURI% 内置对象。

当被调用时执行以下步骤:

  1. uriString 为 ? ToString(uri)。
  2. extraUnescaped";/?:@&=+$,#"
  3. 返回 ? Encode(uriString, extraUnescaped)。

19.2.6.4 encodeURIComponent ( uriComponent )

此函数计算 UTF-16 编码(6.1.4)URI 的新版本,其中某些代码点的每个实例都被表示代码点的 UTF-8 编码的一个、两个、三个或四个转义序列替换。

它是 %encodeURIComponent% 内置对象。

当被调用时执行以下步骤:

  1. componentString 为 ? ToString(uriComponent)。
  2. extraUnescaped 为空字符串。
  3. 返回 ? Encode(componentString, extraUnescaped)。

19.2.6.5 Encode ( string, extraUnescaped )

抽象操作 Encode 接受参数 string(一个字符串)和 extraUnescaped(一个字符串),返回一个包含字符串的 正常完成或一个 抛出完成。它执行 URI 编码和转义,将 string 解释为 6.1.4 中描述的 UTF-16 编码代码点序列。如果字符在 RFC 2396 中被标识为未保留的或出现在 extraUnescaped 中,则不进行转义。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. R 为空字符串。
  3. alwaysUnescapedASCII 单词字符"-.!~*'()"字符串连接
  4. unescapedSetalwaysUnescapedextraUnescaped字符串连接
  5. k 为 0。
  6. 重复,当 k < len 时,
    1. Cstring 中索引 k 处的代码单元。
    2. 如果 unescapedSet 包含 C,那么
      1. kk + 1。
      2. RRC字符串连接
    3. 否则,
      1. cpCodePointAt(string, k)。
      2. 如果 cp.[[IsUnpairedSurrogate]]true,抛出 URIError 异常。
      3. kk + cp.[[CodeUnitCount]]
      4. Octets 为通过对 cp.[[CodePoint]] 应用 UTF-8 变换得到的八位字节的 列表
      5. 对于 Octets 的每个元素 octet,执行
        1. hexoctet 的字符串表示,格式化为大写十六进制数。
        2. RR"%"StringPad(hex, 2, "0", start) 的 字符串连接
  7. 返回 R

因为百分号编码用于表示单个八位字节,所以单个代码点可能表示为多个连续的转义序列(其 8 位 UTF-8 代码单元的每一个对应一个)。

19.2.6.6 Decode ( string, preserveEscapeSet )

抽象操作 Decode 接受参数 string(一个字符串)和 preserveEscapeSet(一个字符串),返回一个包含字符串的 正常完成或一个 抛出完成。它执行 URI 反转义和解码,保留与 preserveEscapeSet 中的基本拉丁字符对应的任何转义序列。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. R 为空字符串。
  3. k 为 0。
  4. 重复,当 k < len 时,
    1. Cstring 中索引 k 处的代码单元。
    2. SC
    3. 如果 C 是代码单元 0x0025(百分号),那么
      1. 如果 k + 3 > len,抛出 URIError 异常。
      2. escapestringkk + 3 的 子字符串
      3. BParseHexOctet(string, k + 1)。
      4. 如果 B 不是一个 整数,抛出 URIError 异常。
      5. kk + 2。
      6. nB 中前导 1 位的数量。
      7. 如果 n = 0,那么
        1. asciiChar 为数值为 B 的代码单元。
        2. 如果 preserveEscapeSet 包含 asciiChar,设 Sescape。否则,设 SasciiChar
      8. 否则,
        1. 如果 n = 1 或 n > 4,抛出 URIError 异常。
        2. Octets 为 « B »。
        3. j 为 1。
        4. 重复,当 j < n 时,
          1. kk + 1。
          2. 如果 k + 3 > len,抛出 URIError 异常。
          3. 如果 string 中索引 k 处的代码单元不是代码单元 0x0025(百分号),抛出 URIError 异常。
          4. continuationByteParseHexOctet(string, k + 1)。
          5. 如果 continuationByte 不是一个 整数,抛出 URIError 异常。
          6. continuationByte 添加到 Octets
          7. kk + 2。
          8. jj + 1。
        5. 断言Octets 的长度是 n
        6. 如果 Octets 不包含 Unicode 代码点的有效 UTF-8 编码,抛出 URIError 异常。
        7. V 为通过对 Octets 应用 UTF-8 变换获得的代码点,即从八位字节的 列表到 21 位值。
        8. SUTF16EncodeCodePoint(V)。
    4. RRS字符串连接
    5. kk + 1。
  5. 返回 R

RFC 3629 禁止解码无效的 UTF-8 八位字节序列。例如,无效序列 0xC0 0x80 不得解码为代码单元 0x0000。Decode 算法的实现在遇到此类无效序列时必须抛出 URIError

19.2.6.7 ParseHexOctet ( string, position )

抽象操作 ParseHexOctet 接受参数 string(一个字符串)和 position(一个非负 整数),返回一个非负 整数或一个非空的 SyntaxError 对象的 列表。它解析 string 中指定 position 处的两个十六进制字符序列为一个无符号 8 位 整数。当被调用时执行以下步骤:

  1. lenstring 的长度。
  2. 断言position + 2 ≤ len
  3. hexDigitsstringpositionposition + 2 的 子字符串
  4. parseResultParseText(hexDigits, HexDigits[~Sep])。
  5. 如果 parseResult 不是一个 解析节点,返回 parseResult
  6. nparseResult 的 MV。
  7. 断言n 在从 0 到 255 的 闭区间内。
  8. 返回 n

19.3 全局对象的构造器属性

19.3.1 AggregateError ( . . . )

参见 20.5.7.1

19.3.2 Array ( . . . )

参见 23.1.1

19.3.3 ArrayBuffer ( . . . )

参见 25.1.4

19.3.4 BigInt ( . . . )

参见 21.2.1

19.3.5 BigInt64Array ( . . . )

参见 23.2.5

19.3.6 BigUint64Array ( . . . )

参见 23.2.5

19.3.7 Boolean ( . . . )

参见 20.3.1

19.3.8 DataView ( . . . )

参见 25.3.2

19.3.9 Date ( . . . )

参见 21.4.2

19.3.10 Error ( . . . )

参见 20.5.1

19.3.11 EvalError ( . . . )

参见 20.5.5.1

19.3.12 FinalizationRegistry ( . . . )

参见 26.2.1

19.3.13 Float16Array ( . . . )

参见 23.2.5

19.3.14 Float32Array ( . . . )

参见 23.2.5

19.3.15 Float64Array ( . . . )

参见 23.2.5

19.3.16 Function ( . . . )

参见 20.2.1

19.3.17 Int8Array ( . . . )

参见 23.2.5

19.3.18 Int16Array ( . . . )

参见 23.2.5

19.3.19 Int32Array ( . . . )

参见 23.2.5

19.3.20 Iterator ( . . . )

参见 27.1.3.1

19.3.21 Map ( . . . )

参见 24.1.1

19.3.22 Number ( . . . )

参见 21.1.1

19.3.23 Object ( . . . )

参见 20.1.1

19.3.24 Promise ( . . . )

参见 27.2.3

19.3.25 Proxy ( . . . )

参见 28.2.1

19.3.26 RangeError ( . . . )

参见 20.5.5.2

19.3.27 ReferenceError ( . . . )

参见 20.5.5.3

19.3.28 RegExp ( . . . )

参见 22.2.4

19.3.29 Set ( . . . )

参见 24.2.2

19.3.30 SharedArrayBuffer ( . . . )

参见 25.2.3

19.3.31 String ( . . . )

参见 22.1.1

19.3.32 Symbol ( . . . )

参见 20.4.1

19.3.33 SyntaxError ( . . . )

参见 20.5.5.4

19.3.34 TypeError ( . . . )

参见 20.5.5.5

19.3.35 Uint8Array ( . . . )

参见 23.2.5

19.3.36 Uint8ClampedArray ( . . . )

参见 23.2.5

19.3.37 Uint16Array ( . . . )

参见 23.2.5

19.3.38 Uint32Array ( . . . )

参见 23.2.5

19.3.39 URIError ( . . . )

参见 20.5.5.6

19.3.40 WeakMap ( . . . )

参见 24.3.1

19.3.41 WeakRef ( . . . )

参见 26.1.1

19.3.42 WeakSet ( . . . )

参见 24.4

19.4 全局对象的其他属性

19.4.1 Atomics

参见 25.4

19.4.2 JSON

参见 25.5

19.4.3 Math

参见 21.3

19.4.4 Reflect

参见 28.1

20 基础对象

20.1 Object 对象

20.1.1 Object 构造器

Object 构造器

  • %Object%
  • 全局对象"Object" 属性的初始值。
  • 当作为 构造器调用时,创建一个新的 普通对象
  • 当作为函数而不是 构造器调用时,执行类型转换。
  • 可以用作类定义的 extends 子句的值。

20.1.1.1 Object ( [ value ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 既不是 undefined 也不是 活动函数对象,那么
    1. 返回 ? OrdinaryCreateFromConstructor(NewTarget, "%Object.prototype%")。
  2. 如果 valueundefinednull,返回 OrdinaryObjectCreate(%Object.prototype%)。
  3. 返回 ! ToObject(value)。

20.1.2 Object 构造器的属性

Object 构造器

  • 有一个 [[Prototype]] 内部槽,其值是 %Function.prototype%
  • 有一个 "length" 属性,其值是 1𝔽
  • 有以下附加属性:

20.1.2.1 Object.assign ( target, ...sources )

此函数从一个或多个源对象复制所有可枚举自有属性的值到 target 对象。

当被调用时执行以下步骤:

  1. to 为 ? ToObject(target)。
  2. 如果只传递了一个参数,返回 to
  3. 对于 sources 的每个元素 nextSource,执行
    1. 如果 nextSource 既不是 undefined 也不是 null,那么
      1. from 为 ! ToObject(nextSource)。
      2. keys 为 ? from.[[OwnPropertyKeys]]()
      3. 对于 keys 的每个元素 nextKey,执行
        1. desc 为 ? from.[[GetOwnProperty]](nextKey)。
        2. 如果 desc 不是 undefineddesc.[[Enumerable]]true,那么
          1. propValue 为 ? Get(from, nextKey)。
          2. 执行 ? Set(to, nextKey, propValue, true)。
  4. 返回 to

此函数的 "length" 属性是 2𝔽

20.1.2.2 Object.create ( O, Properties )

此函数创建一个具有指定原型的新对象。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象O 不是 null,抛出 TypeError 异常。
  2. objOrdinaryObjectCreate(O)。
  3. 如果 Properties 不是 undefined,那么
    1. 返回 ? ObjectDefineProperties(obj, Properties)。
  4. 返回 obj

20.1.2.3 Object.defineProperties ( O, Properties )

此函数添加自有属性和/或更新对象现有自有属性的特性。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象,抛出 TypeError 异常。
  2. 返回 ? ObjectDefineProperties(O, Properties)。

20.1.2.3.1 ObjectDefineProperties ( O, Properties )

抽象操作 ObjectDefineProperties 接受参数 O(一个对象)和 Properties(一个 ECMAScript 语言值),返回一个包含对象的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. props 为 ? ToObject(Properties)。
  2. keys 为 ? props.[[OwnPropertyKeys]]()
  3. descriptors 为一个新的空 列表
  4. 对于 keys 的每个元素 nextKey,执行
    1. propDesc 为 ? props.[[GetOwnProperty]](nextKey)。
    2. 如果 propDesc 不是 undefinedpropDesc.[[Enumerable]]true,那么
      1. descObj 为 ? Get(props, nextKey)。
      2. desc 为 ? ToPropertyDescriptor(descObj)。
      3. 记录 { [[Key]]: nextKey, [[Descriptor]]: desc } 追加到 descriptors
  5. 对于 descriptors 的每个元素 property,执行
    1. 执行 ? DefinePropertyOrThrow(O, property.[[Key]], property.[[Descriptor]])。
  6. 返回 O

20.1.2.4 Object.defineProperty ( O, P, Attributes )

此函数添加一个自有属性和/或更新对象现有自有属性的特性。

当被调用时执行以下步骤:

  1. 如果 O 不是一个对象,抛出 TypeError 异常。
  2. key 为 ? ToPropertyKey(P)。
  3. desc 为 ? ToPropertyDescriptor(Attributes)。
  4. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  5. 返回 O

20.1.2.5 Object.entries ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. entryList 为 ? EnumerableOwnProperties(obj, key+value)。
  3. 返回 CreateArrayFromList(entryList)。

20.1.2.6 Object.freeze ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? SetIntegrityLevel(O, frozen)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.7 Object.fromEntries ( iterable )

此函数在被调用时执行以下步骤:

  1. 执行 ? RequireObjectCoercible(iterable)。
  2. objOrdinaryObjectCreate(%Object.prototype%)。
  3. 断言obj 是一个可扩展的 普通对象,没有自有属性。
  4. closure 为一个新的 抽象闭包,参数为 (key, value),捕获 obj,当被调用时执行以下步骤:
    1. propertyKey 为 ? ToPropertyKey(key)。
    2. 执行 ! CreateDataPropertyOrThrow(obj, propertyKey, value)。
    3. 返回 undefined
  5. adderCreateBuiltinFunction(closure, 2, "", « »)。
  6. 返回 ? AddEntriesFromIterable(obj, iterable, adder)。
adder 创建的函数永远不会直接被 ECMAScript 代码访问。

20.1.2.8 Object.getOwnPropertyDescriptor ( O, P )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. key 为 ? ToPropertyKey(P)。
  3. desc 为 ? obj.[[GetOwnProperty]](key)。
  4. 返回 FromPropertyDescriptor(desc)。

20.1.2.9 Object.getOwnPropertyDescriptors ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. ownKeys 为 ? obj.[[OwnPropertyKeys]]()
  3. descriptorsOrdinaryObjectCreate(%Object.prototype%)。
  4. 对于 ownKeys 的每个元素 key,执行
    1. desc 为 ? obj.[[GetOwnProperty]](key)。
    2. descriptorFromPropertyDescriptor(desc)。
    3. 如果 descriptor 不是 undefined,执行 ! CreateDataPropertyOrThrow(descriptors, key, descriptor)。
  5. 返回 descriptors

20.1.2.10 Object.getOwnPropertyNames ( O )

此函数在被调用时执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(O, string))。

20.1.2.11 Object.getOwnPropertySymbols ( O )

此函数在被调用时执行以下步骤:

  1. 返回 CreateArrayFromList(? GetOwnPropertyKeys(O, symbol))。

20.1.2.11.1 GetOwnPropertyKeys ( O, type )

抽象操作 GetOwnPropertyKeys 接受参数 O(一个 ECMAScript 语言值)和 typestringsymbol),返回一个包含 属性键列表正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. keys 为 ? obj.[[OwnPropertyKeys]]()
  3. nameList 为一个新的空 列表
  4. 对于 keys 的每个元素 nextKey,执行
    1. 如果 nextKey 是一个符号typesymbol,或者如果 nextKey 是一个字符串typestring,那么
      1. nextKey 追加到 nameList
  5. 返回 nameList

20.1.2.12 Object.getPrototypeOf ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. 返回 ? obj.[[GetPrototypeOf]]()

20.1.2.13 Object.groupBy ( items, callback )

callback 应该是一个接受两个参数的函数。groupBy 按升序为 items 中的每个元素调用一次 callback,并构造一个新对象。callback 返回的每个值都被强制转换为 属性键。对于每个这样的 属性键,结果对象有一个属性,其键是该 属性键,其值是一个数组,包含 callback 返回值强制转换为该键的所有元素。

callback 用两个参数调用:元素的值和元素的索引。

groupBy 的返回值是一个不继承自 %Object.prototype% 的对象。

此函数在被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, property)。
  2. objOrdinaryObjectCreate(null)。
  3. 对于 groups 的每个 记录 { [[Key]], [[Elements]] } g,执行
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. 执行 ! CreateDataPropertyOrThrow(obj, g.[[Key]], elements)。
  4. 返回 obj

20.1.2.14 Object.hasOwn ( O, P )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. key 为 ? ToPropertyKey(P)。
  3. 返回 ? HasOwnProperty(obj, key)。

20.1.2.15 Object.is ( value1, value2 )

此函数在被调用时执行以下步骤:

  1. 返回 SameValue(value1, value2)。

20.1.2.16 Object.isExtensible ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 false
  2. 返回 ? IsExtensible(O)。

20.1.2.17 Object.isFrozen ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 true
  2. 返回 ? TestIntegrityLevel(O, frozen)。

20.1.2.18 Object.isSealed ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 true
  2. 返回 ? TestIntegrityLevel(O, sealed)。

20.1.2.19 Object.keys ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. keyList 为 ? EnumerableOwnProperties(obj, key)。
  3. 返回 CreateArrayFromList(keyList)。

20.1.2.20 Object.preventExtensions ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? O.[[PreventExtensions]]()
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.21 Object.prototype

Object.prototype 的初始值是 Object 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.1.2.22 Object.seal ( O )

此函数在被调用时执行以下步骤:

  1. 如果 O 不是一个对象,返回 O
  2. status 为 ? SetIntegrityLevel(O, sealed)。
  3. 如果 statusfalse,抛出 TypeError 异常。
  4. 返回 O

20.1.2.23 Object.setPrototypeOf ( O, proto )

此函数在被调用时执行以下步骤:

  1. O 为 ? RequireObjectCoercible(O)。
  2. 如果 proto 不是一个对象proto 不是 null,抛出 TypeError 异常。
  3. 如果 O 不是一个对象,返回 O
  4. status 为 ? O.[[SetPrototypeOf]](proto)。
  5. 如果 statusfalse,抛出 TypeError 异常。
  6. 返回 O

20.1.2.24 Object.values ( O )

此函数在被调用时执行以下步骤:

  1. obj 为 ? ToObject(O)。
  2. valueList 为 ? EnumerableOwnProperties(obj, value)。
  3. 返回 CreateArrayFromList(valueList)。

20.1.3 Object 原型对象的属性

Object 原型对象

  • %Object.prototype%
  • 有一个 [[Extensible]] 内部槽,其值是 true
  • 有为 普通对象定义的内部方法,除了 [[SetPrototypeOf]] 方法,它按照 10.4.7.1 中的定义。 (因此,它是一个 不可变原型外来对象。)
  • 有一个 [[Prototype]] 内部槽,其值是 null

20.1.3.1 Object.prototype.constructor

Object.prototype.constructor 的初始值是 %Object%

20.1.3.2 Object.prototype.hasOwnProperty ( V )

此方法在被调用时执行以下步骤:

  1. P 为 ? ToPropertyKey(V)。
  2. O 为 ? ToObject(this 值)。
  3. 返回 ? HasOwnProperty(O, P)。

步骤 12 的顺序是为了确保,即使 this 值是 undefinednull,在此规范的以前版本中步骤 1 会抛出的任何异常都将继续被抛出。

20.1.3.3 Object.prototype.isPrototypeOf ( V )

此方法在被调用时执行以下步骤:

  1. 如果 V 不是一个对象,返回 false
  2. O 为 ? ToObject(this 值)。
  3. 重复,
    1. V 为 ? V.[[GetPrototypeOf]]()
    2. 如果 Vnull,返回 false
    3. 如果 SameValue(O, V) 是 true,返回 true

步骤 12 的顺序保持了此规范的以前版本为 V 不是对象且 this 值是 undefinednull 的情况指定的行为。

20.1.3.4 Object.prototype.propertyIsEnumerable ( V )

此方法在被调用时执行以下步骤:

  1. P 为 ? ToPropertyKey(V)。
  2. O 为 ? ToObject(this 值)。
  3. desc 为 ? O.[[GetOwnProperty]](P)。
  4. 如果 descundefined,返回 false
  5. 返回 desc.[[Enumerable]]
注 1

此方法不考虑原型链中的对象。

注 2

步骤 12 的顺序是为了确保,即使 this 值是 undefinednull,在此规范的以前版本中步骤 1 会抛出的任何异常都将继续被抛出。

20.1.3.5 Object.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

此方法在被调用时执行以下步骤:

  1. Othis 值。
  2. 返回 ? Invoke(O, "toString")。

此方法的可选参数未被使用,但旨在对应 ECMA-402 toLocaleString 方法使用的参数模式。不包含 ECMA-402 支持的实现不得将这些参数位置用于其他目的。

注 1

此方法为没有区域敏感的 toString 行为的对象提供通用的 toLocaleString 实现。ArrayNumberDate%TypedArray% 提供它们自己的区域敏感的 toLocaleString 方法。

注 2

ECMA-402 故意不为此默认实现提供替代方案。

20.1.3.6 Object.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. 如果 this 值是 undefined,返回 "[object Undefined]"
  2. 如果 this 值是 null,返回 "[object Null]"
  3. O 为 ! ToObject(this 值)。
  4. isArray 为 ? IsArray(O)。
  5. 如果 isArraytrue,设 builtinTag"Array"
  6. 否则如果 O 有一个 [[ParameterMap]] 内部槽,设 builtinTag"Arguments"
  7. 否则如果 O 有一个 [[Call]] 内部方法,设 builtinTag"Function"
  8. 否则如果 O 有一个 [[ErrorData]] 内部槽,设 builtinTag"Error"
  9. 否则如果 O 有一个 [[BooleanData]] 内部槽,设 builtinTag"Boolean"
  10. 否则如果 O 有一个 [[NumberData]] 内部槽,设 builtinTag"Number"
  11. 否则如果 O 有一个 [[StringData]] 内部槽,设 builtinTag"String"
  12. 否则如果 O 有一个 [[DateValue]] 内部槽,设 builtinTag"Date"
  13. 否则如果 O 有一个 [[RegExpMatcher]] 内部槽,设 builtinTag"RegExp"
  14. 否则,设 builtinTag"Object"
  15. tag 为 ? Get(O, %Symbol.toStringTag%)。
  16. 如果 tag 不是一个字符串,设 tagbuiltinTag
  17. 返回 "[object "tag"]"字符串连接

历史上,此方法偶尔被用来访问 [[Class]] 内部槽的字符串值,该内部槽在此规范的以前版本中用作各种内建对象的名义类型标签。上述 toString 的定义为使用 toString 作为那些特定类型的内建对象测试的遗留代码保持兼容性。它不为其他类型的内建或程序定义的对象提供可靠的类型测试机制。此外,程序可以以会使此类遗留类型测试的可靠性失效的方式使用 %Symbol.toStringTag%

20.1.3.7 Object.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ToObject(this 值)。

20.1.3.8 Object.prototype.__proto__

Object.prototype.__proto__ 是一个 访问器属性,有特性 { [[Enumerable]]: false[[Configurable]]: true }。[[Get]][[Set]] 特性定义如下:

20.1.3.8.1 get Object.prototype.__proto__

[[Get]] 特性的值是一个不需要参数的内建函数。当被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 ? O.[[GetPrototypeOf]]()

20.1.3.8.2 set Object.prototype.__proto__

[[Set]] 特性的值是一个接受参数 proto 的内建函数。当被调用时执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 proto 不是一个对象proto 不是 null,返回 undefined
  3. 如果 O 不是一个对象,返回 undefined
  4. status 为 ? O.[[SetPrototypeOf]](proto)。
  5. 如果 statusfalse,抛出 TypeError 异常。
  6. 返回 undefined

20.1.3.9 遗留的 Object.prototype 访问器方法

20.1.3.9.1 Object.prototype.__defineGetter__ ( P, getter )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 如果 IsCallable(getter) 是 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Get]]: getter[[Enumerable]]: true[[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(P)。
  5. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  6. 返回 undefined

20.1.3.9.2 Object.prototype.__defineSetter__ ( P, setter )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 如果 IsCallable(setter) 是 false,抛出 TypeError 异常。
  3. desc 为 PropertyDescriptor { [[Set]]: setter[[Enumerable]]: true[[Configurable]]: true }。
  4. key 为 ? ToPropertyKey(P)。
  5. 执行 ? DefinePropertyOrThrow(O, key, desc)。
  6. 返回 undefined

20.1.3.9.3 Object.prototype.__lookupGetter__ ( P )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. key 为 ? ToPropertyKey(P)。
  3. 重复,
    1. desc 为 ? O.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(desc) 是 true,返回 desc.[[Get]]
      2. 返回 undefined
    3. O 为 ? O.[[GetPrototypeOf]]()
    4. 如果 Onull,返回 undefined

20.1.3.9.4 Object.prototype.__lookupSetter__ ( P )

此方法在被调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. key 为 ? ToPropertyKey(P)。
  3. 重复,
    1. desc 为 ? O.[[GetOwnProperty]](key)。
    2. 如果 desc 不是 undefined,那么
      1. 如果 IsAccessorDescriptor(desc) 是 true,返回 desc.[[Set]]
      2. 返回 undefined
    3. O 为 ? O.[[GetPrototypeOf]]()
    4. 如果 Onull,返回 undefined

20.1.4 Object 实例的属性

Object 实例除了从 Object 原型对象继承的属性外,没有特殊属性。

20.2 Function 对象

20.2.1 Function 构造器

Function 构造器

  • %Function%
  • 全局对象"Function" 属性的初始值。
  • 当作为函数而不是作为 构造器调用时,创建并初始化一个新的 函数对象。因此函数调用 Function(…) 等价于使用相同参数的对象创建表达式 new Function(…)
  • 可以用作类定义中 extends 子句的值。打算继承指定的 Function 行为的子类 构造器必须包含一个对 Function 构造器super 调用,以创建和初始化具有内建函数行为所需的内部槽的子类实例。所有用于定义 函数对象的 ECMAScript 语法形式都创建 Function 的实例。除了内建的 GeneratorFunction、AsyncFunction 和 AsyncGeneratorFunction 子类之外,没有语法方式来创建 Function 子类的实例。

20.2.1.1 Function ( ...parameterArgs, bodyArg )

最后一个参数(如果有的话)指定函数的主体(可执行代码);任何前面的参数指定形式参数。

此函数在被调用时执行以下步骤:

  1. C活动函数对象
  2. 如果 bodyArg 不存在,设 bodyArg 为空字符串。
  3. 返回 ? CreateDynamicFunction(C, NewTarget, normal, parameterArgs, bodyArg)。

为要指定的每个形式参数都有一个参数是允许的但不是必需的。例如,以下三个表达式都产生相同的结果:

new Function("a", "b", "c", "return a+b+c")
                new Function("a, b, c", "return a+b+c")
                new Function("a,b", "c", "return a+b+c")

20.2.1.1.1 CreateDynamicFunction ( constructor, newTarget, kind, parameterArgs, bodyArg )

抽象操作 CreateDynamicFunction 接受参数 constructor(一个 构造器)、newTarget(一个 构造器undefined)、kindnormalgeneratorasyncasync-generator)、parameterArgsECMAScript 语言值列表)和 bodyArg(一个 ECMAScript 语言值),返回一个 包含 ECMAScript 函数对象正常完成或一个 抛出完成constructor 是执行此操作的 构造器函数。newTarget 是最初应用 new构造器parameterArgsbodyArg 反映传递给 constructor 的参数值。当被调用时执行以下步骤:

  1. 如果 newTargetundefined,设 newTargetconstructor
  2. 如果 kindnormal,那么
    1. prefix"function"
    2. exprSym 为语法符号 FunctionExpression
    3. bodySym 为语法符号 FunctionBody[~Yield, ~Await]
    4. parameterSym 为语法符号 FormalParameters[~Yield, ~Await]
    5. fallbackProto"%Function.prototype%"
  3. 否则如果 kindgenerator,那么
    1. prefix"function*"
    2. exprSym 为语法符号 GeneratorExpression
    3. bodySym 为语法符号 GeneratorBody
    4. parameterSym 为语法符号 FormalParameters[+Yield, ~Await]
    5. fallbackProto"%GeneratorFunction.prototype%"
  4. 否则如果 kindasync,那么
    1. prefix"async function"
    2. exprSym 为语法符号 AsyncFunctionExpression
    3. bodySym 为语法符号 AsyncFunctionBody
    4. parameterSym 为语法符号 FormalParameters[~Yield, +Await]
    5. fallbackProto"%AsyncFunction.prototype%"
  5. 否则,
    1. 断言kindasync-generator
    2. prefix"async function*"
    3. exprSym 为语法符号 AsyncGeneratorExpression
    4. bodySym 为语法符号 AsyncGeneratorBody
    5. parameterSym 为语法符号 FormalParameters[+Yield, +Await]
    6. fallbackProto"%AsyncGeneratorFunction.prototype%"
  6. argCountparameterArgs 中元素的数量。
  7. parameterStrings 为一个新的空 列表
  8. 对于 parameterArgs 的每个元素 arg,执行
    1. 将 ? ToString(arg) 追加到 parameterStrings
  9. bodyString 为 ? ToString(bodyArg)。
  10. currentRealm当前 Realm 记录
  11. 执行 ? HostEnsureCanCompileStrings(currentRealm, parameterStrings, bodyString, false)。
  12. P 为空字符串。
  13. 如果 argCount > 0,那么
    1. PparameterStrings[0]。
    2. k 为 1。
    3. 重复,当 k < argCount 时,
      1. nextArgStringparameterStrings[k]。
      2. PP","(逗号)和 nextArgString字符串连接
      3. kk + 1。
  14. bodyParseString 为 0x000A(换行符)、bodyString 和 0x000A(换行符)的 字符串连接
  15. sourceStringprefix" anonymous("P、0x000A(换行符)、") {"bodyParseString"}"字符串连接
  16. sourceTextStringToCodePoints(sourceString)。
  17. parametersParseText(P, parameterSym)。
  18. 如果 parameters 是一个错误的 列表,抛出 SyntaxError 异常。
  19. bodyParseText(bodyParseString, bodySym)。
  20. 如果 body 是一个错误的 列表,抛出 SyntaxError 异常。
  21. 注:参数和主体分别解析以确保各自都是有效的。例如,new Function("/*", "*/ ) {") 不会计算为函数。
  22. 注:如果达到这一步,sourceText 必须具有 exprSym 的语法(尽管反向含义不成立)。接下来两步的目的是执行直接应用于 exprSym 的任何早期错误规则。
  23. exprParseText(sourceText, exprSym)。
  24. 如果 expr 是一个错误的 列表,抛出 SyntaxError 异常。
  25. proto 为 ? GetPrototypeFromConstructor(newTarget, fallbackProto)。
  26. envcurrentRealm.[[GlobalEnv]]
  27. privateEnvnull
  28. FOrdinaryFunctionCreate(proto, sourceText, parameters, body, non-lexical-this, env, privateEnv)。
  29. 执行 SetFunctionName(F, "anonymous")。
  30. 如果 kindgenerator,那么
    1. prototypeOrdinaryObjectCreate(%GeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  31. 否则如果 kindasync-generator,那么
    1. prototypeOrdinaryObjectCreate(%AsyncGeneratorPrototype%)。
    2. 执行 ! DefinePropertyOrThrow(F, "prototype", PropertyDescriptor { [[Value]]: prototype, [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  32. 否则如果 kindnormal,那么
    1. 执行 MakeConstructor(F)。
  33. 注:kindasync 的函数不可构造且没有 [[Construct]] 内部方法或 "prototype" 属性。
  34. 返回 F

CreateDynamicFunction 在它创建的任何 kind 不是 async 的函数上定义一个 "prototype" 属性,以提供函数将被用作 构造器的可能性。

20.2.2 Function 构造器的属性

Function 构造器

  • 本身是一个内建的 函数对象
  • 有一个 [[Prototype]] 内部槽,其值是 %Function.prototype%
  • 有一个 "length" 属性,其值是 1𝔽
  • 有以下属性:

20.2.2.1 Function.prototype

Function.prototype 的值是 Function 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.2.3 Function 原型对象的属性

Function 原型对象

  • %Function.prototype%
  • 本身是一个内建的 函数对象
  • 接受任何参数并在调用时返回 undefined
  • 没有 [[Construct]] 内部方法;它不能与 new 操作符一起用作 构造器
  • 有一个 [[Prototype]] 内部槽,其值是 %Object.prototype%
  • 没有 "prototype" 属性。
  • 有一个 "length" 属性,其值是 +0𝔽
  • 有一个 "name" 属性,其值是空字符串。

Function 原型对象被指定为 函数对象,以确保与在 ECMAScript 2015 规范之前创建的 ECMAScript 代码的兼容性。

20.2.3.1 Function.prototype.apply ( thisArg, argArray )

此方法在被调用时执行以下步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  3. 如果 argArrayundefinednull,那么
    1. 执行 PrepareForTailCall()。
    2. 返回 ? Call(func, thisArg)。
  4. argList 为 ? CreateListFromArrayLike(argArray)。
  5. 执行 PrepareForTailCall()。
  6. 返回 ? Call(func, thisArg, argList)。
注 1

thisArg 值被不加修改地传递作为 this 值。这是与第3版的变化,在第3版中,undefinednullthisArg 被替换为 全局对象,并且 ToObject 被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg 被不加修改地传递,非严格函数在进入函数时仍然执行这些转换。

注 2

如果 func 是箭头函数或 绑定函数外来对象,那么 thisArg 将在步骤 6 的函数 [[Call]] 中被忽略。

20.2.3.2 Function.prototype.bind ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. Targetthis 值。
  2. 如果 IsCallable(Target) 是 false,抛出 TypeError 异常。
  3. F 为 ? BoundFunctionCreate(Target, thisArg, args)。
  4. L 为 0。
  5. targetHasLength 为 ? HasOwnProperty(Target, "length")。
  6. 如果 targetHasLengthtrue,那么
    1. targetLen 为 ? Get(Target, "length")。
    2. 如果 targetLen 是一个数值,那么
      1. 如果 targetLen+∞𝔽,那么
        1. L 为 +∞。
      2. 否则如果 targetLen-∞𝔽,那么
        1. L 为 0。
      3. 否则,
        1. targetLenAsInt 为 ! ToIntegerOrInfinity(targetLen)。
        2. 断言targetLenAsInt有限的
        3. argCountargs 中元素的数量。
        4. Lmax(targetLenAsInt - argCount, 0)。
  7. 执行 SetFunctionLength(F, L)。
  8. targetName 为 ? Get(Target, "name")。
  9. 如果 targetName 不是字符串,设 targetName 为空字符串。
  10. 执行 SetFunctionName(F, targetName, "bound")。
  11. 返回 F
注 1

使用 Function.prototype.bind 创建的 函数对象外来对象。它们也没有 "prototype" 属性。

注 2

如果 Target 是箭头函数或 绑定函数外来对象,那么传递给此方法的 thisArg 将不会被后续对 F 的调用使用。

20.2.3.3 Function.prototype.call ( thisArg, ...args )

此方法在被调用时执行以下步骤:

  1. functhis 值。
  2. 如果 IsCallable(func) 是 false,抛出 TypeError 异常。
  3. 执行 PrepareForTailCall()。
  4. 返回 ? Call(func, thisArg, args)。
注 1

thisArg 值被不加修改地传递作为 this 值。这是与第3版的变化,在第3版中,undefinednullthisArg 被替换为 全局对象,并且 ToObject 被应用于所有其他值,该结果被传递作为 this 值。尽管 thisArg 被不加修改地传递,非严格函数在进入函数时仍然执行这些转换。

注 2

如果 func 是箭头函数或 绑定函数外来对象,那么 thisArg 将在步骤 4 的函数 [[Call]] 中被忽略。

20.2.3.4 Function.prototype.constructor

Function.prototype.constructor 的初始值是 %Function%

20.2.3.5 Function.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. functhis 值。
  2. 如果 func 是一个对象func 有一个 [[SourceText]] 内部槽,func.[[SourceText]] 是一个 Unicode 码点序列,并且 HostHasSourceTextAvailable(func) 是 true,那么
    1. 返回 CodePointsToString(func.[[SourceText]])。
  3. 如果 func 是一个 内建函数对象,返回 func实现定义的字符串源代码表示。该表示必须具有 NativeFunction 的语法。另外,如果 func 有一个 [[InitialName]] 内部槽且 func.[[InitialName]] 是一个字符串,返回的字符串中与 NativeFunctionAccessoropt PropertyName 匹配的部分必须是 func.[[InitialName]] 的值。
  4. 如果 func 是一个对象IsCallable(func) 是 true,返回 func实现定义的字符串源代码表示。该表示必须具有 NativeFunction 的语法。
  5. 抛出 TypeError 异常。
NativeFunction : function NativeFunctionAccessoropt PropertyName[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { [ native code ] } NativeFunctionAccessor : get set

20.2.3.6 Function.prototype [ %Symbol.hasInstance% ] ( V )

此方法在被调用时执行以下步骤:

  1. Fthis 值。
  2. 返回 ? OrdinaryHasInstance(F, V)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

这是大多数函数继承的 %Symbol.hasInstance% 的默认实现。%Symbol.hasInstance%instanceof 操作符调用,以确定值是否是特定 构造器的实例。诸如

v instanceof F

的表达式计算为

F[%Symbol.hasInstance%](v)

构造器函数可以通过在函数上公开不同的 %Symbol.hasInstance% 方法来控制哪些对象被 instanceof 识别为其实例。

此属性是不可写和不可配置的,以防止可能用于全局暴露绑定函数目标函数的篡改。

此方法的 "name" 属性的值是 "[Symbol.hasInstance]"

20.2.4 Function 实例

每个 Function 实例都是一个 ECMAScript 函数对象,并具有 表 30 中列出的内部槽。使用 Function.prototype.bind 方法(20.2.3.2)创建的 函数对象具有 表 31 中列出的内部槽。

Function 实例有以下属性:

20.2.4.1 length

"length" 属性的值是一个 整数,表示函数期望的典型参数数量。但是,语言允许使用其他数量的参数调用函数。当使用的参数数量与其 "length" 属性指定的数量不同时,函数的行为取决于该函数。此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.2.4.2 name

"name" 属性的值 是一个字符串,用于描述该函数。该名称没有语义意义,但通常是在 ECMAScript 源文本中的定义点用来引用函数的变量或 属性名。此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

本规范没有关联上下文名称的匿名函数对象使用空字符串作为 "name" 属性的值。

20.2.4.3 prototype

可以用作 构造器的 Function 实例有一个 "prototype" 属性。每当创建这样的 Function 实例时,还会创建另一个 普通对象,并且它是函数的 "prototype" 属性的初始值。除非另有说明,"prototype" 属性的值用于初始化当该函数作为 构造器调用时所创建对象的 [[Prototype]] 内部槽。

此属性有特性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

使用 Function.prototype.bind 创建的 函数对象,或通过求值 MethodDefinition(不是 GeneratorMethodAsyncGeneratorMethod)或 ArrowFunction 创建的函数对象没有 "prototype" 属性。

20.2.5 HostHasSourceTextAvailable ( func )

宿主定义的抽象操作 HostHasSourceTextAvailable 接受参数 func(一个 函数对象)并返回一个布尔值。它允许 宿主环境阻止为 func 提供源文本。

HostHasSourceTextAvailable 的实现必须符合以下要求:

  • 它必须相对于其参数是确定性的。每次使用特定的 func 作为参数调用时,它必须返回相同的结果。

HostHasSourceTextAvailable 的默认实现是返回 true

20.3 Boolean 对象

20.3.1 Boolean 构造器

Boolean 构造器

  • %Boolean%
  • 全局对象"Boolean" 属性的初始值。
  • 当作为 构造器调用时,创建并初始化一个新的 Boolean 对象。
  • 当作为函数而不是作为 构造器调用时,执行类型转换。
  • 可以用作类定义中 extends 子句的值。打算继承指定的 Boolean 行为的子类 构造器必须包含一个对 Boolean 构造器super 调用,以创建和初始化具有 [[BooleanData]] 内部槽的子类实例。

20.3.1.1 Boolean ( value )

此函数在被调用时执行以下步骤:

  1. bToBoolean(value)。
  2. 如果 NewTarget 是 undefined,返回 b
  3. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Boolean.prototype%", « [[BooleanData]] »)。
  4. O.[[BooleanData]]b
  5. 返回 O

20.3.2 Boolean 构造器的属性

Boolean 构造器

20.3.2.1 Boolean.prototype

Boolean.prototype 的初始值是 Boolean 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.3.3 Boolean 原型对象的属性

Boolean 原型对象

  • %Boolean.prototype%
  • 是一个 普通对象
  • 本身是一个 Boolean 对象;它有一个 [[BooleanData]] 内部槽,值为 false
  • 有一个 [[Prototype]] 内部槽,其值是 %Object.prototype%

20.3.3.1 Boolean.prototype.constructor

Boolean.prototype.constructor 的初始值是 %Boolean%

20.3.3.2 Boolean.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. b 为 ? ThisBooleanValue(this value)。
  2. 如果 btrue,返回 "true";否则返回 "false"

20.3.3.3 Boolean.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisBooleanValue(this value)。

20.3.3.3.1 ThisBooleanValue ( value )

抽象操作 ThisBooleanValue 接受参数 value(一个 ECMAScript 语言值)并返回一个 包含布尔值的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是一个布尔值,返回 value
  2. 如果 value 是一个对象value 有一个 [[BooleanData]] 内部槽,那么
    1. bvalue.[[BooleanData]]
    2. 断言b 是一个布尔值
    3. 返回 b
  3. 抛出 TypeError 异常。

20.3.4 Boolean 实例的属性

Boolean 实例是从 Boolean 原型对象继承属性的 普通对象。Boolean 实例有一个 [[BooleanData]] 内部槽。[[BooleanData]] 内部槽是此 Boolean 对象表示的布尔值。

20.4 Symbol 对象

20.4.1 Symbol 构造器

Symbol 构造器

  • %Symbol%
  • 全局对象"Symbol" 属性的初始值。
  • 当作为函数调用时返回一个新的 Symbol 值。
  • 不打算与 new 操作符一起使用。
  • 不打算被子类化。
  • 可以用作类定义中 extends 子句的值,但对它的 super 调用将导致异常。

20.4.1.1 Symbol ( [ description ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 不是 undefined,抛出 TypeError 异常。
  2. 如果 descriptionundefined,设 descStringundefined
  3. 否则,设 descString 为 ? ToString(description)。
  4. 返回一个新的 Symbol,其 [[Description]]descString

20.4.2 Symbol 构造器的属性

Symbol 构造器

20.4.2.1 Symbol.asyncIterator

Symbol.asyncIterator 的初始值是众所周知的符号 %Symbol.asyncIterator%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.2 Symbol.for ( key )

此函数在被调用时执行以下步骤:

  1. stringKey 为 ? ToString(key)。
  2. 对于 GlobalSymbolRegistry 列表的每个元素 e,执行
    1. 如果 e.[[Key]]stringKey, 返回 e.[[Symbol]]
  3. 断言GlobalSymbolRegistry 列表当前不包含 stringKey 的条目。
  4. newSymbol 为一个新的 Symbol,其 [[Description]]stringKey
  5. 将 GlobalSymbolRegistry 记录 { [[Key]]: stringKey, [[Symbol]]: newSymbol } 追加到 GlobalSymbolRegistry 列表
  6. 返回 newSymbol

GlobalSymbolRegistry 列表是一个只能追加的 列表,全局可用。它被所有 Realm 共享。在任何 ECMAScript 代码的求值之前,它被初始化为一个新的空 列表。GlobalSymbolRegistry 列表的元素是具有 表 63 中定义的结构的 记录

表 63:GlobalSymbolRegistry 记录字段
字段名 用法
[[Key]] 一个字符串 用于全局标识 Symbol 的字符串键。
[[Symbol]] 一个 Symbol 可以从任何 Realm 检索的符号。

20.4.2.3 Symbol.hasInstance

Symbol.hasInstance 的初始值是众所周知的符号 %Symbol.hasInstance%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.4 Symbol.isConcatSpreadable

Symbol.isConcatSpreadable 的初始值是众所周知的符号 %Symbol.isConcatSpreadable%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.5 Symbol.iterator

Symbol.iterator 的初始值是众所周知的符号 %Symbol.iterator%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.6 Symbol.keyFor ( sym )

此函数在被调用时执行以下步骤:

  1. 如果 sym 不是 Symbol,抛出 TypeError 异常。
  2. 返回 KeyForSymbol(sym)。

20.4.2.7 Symbol.match

Symbol.match 的初始值是众所周知的符号 %Symbol.match%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.8 Symbol.matchAll

Symbol.matchAll 的初始值是众所周知的符号 %Symbol.matchAll%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.9 Symbol.prototype

Symbol.prototype 的初始值是 Symbol 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.10 Symbol.replace

Symbol.replace 的初始值是众所周知的符号 %Symbol.replace%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.11 Symbol.search

Symbol.search 的初始值是众所周知的符号 %Symbol.search%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.12 Symbol.species

Symbol.species 的初始值是众所周知的符号 %Symbol.species%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.13 Symbol.split

Symbol.split 的初始值是众所周知的符号 %Symbol.split%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.14 Symbol.toPrimitive

Symbol.toPrimitive 的初始值是众所周知的符号 %Symbol.toPrimitive%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.15 Symbol.toStringTag

Symbol.toStringTag 的初始值是众所周知的符号 %Symbol.toStringTag%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.2.16 Symbol.unscopables

Symbol.unscopables 的初始值是众所周知的符号 %Symbol.unscopables%表 1)。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.4.3 Symbol 原型对象的属性

Symbol 原型对象

20.4.3.1 Symbol.prototype.constructor

Symbol.prototype.constructor 的初始值是 %Symbol%

20.4.3.2 get Symbol.prototype.description

Symbol.prototype.description 是一个 访问器属性,其 set 访问器函数是 undefined。其 get 访问器函数在被调用时执行以下步骤:

  1. sthis 值。
  2. sym 为 ? ThisSymbolValue(s)。
  3. 返回 sym.[[Description]]

20.4.3.3 Symbol.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. sym 为 ? ThisSymbolValue(this value)。
  2. 返回 SymbolDescriptiveString(sym)。

20.4.3.3.1 SymbolDescriptiveString ( sym )

抽象操作 SymbolDescriptiveString 接受参数 sym(一个 Symbol)并返回一个字符串。当被调用时执行以下步骤:

  1. descsym[[Description]] 值。
  2. 如果 descundefined,设 desc 为空字符串。
  3. 断言desc 是一个字符串
  4. 返回 "Symbol("desc")"字符串连接

20.4.3.4 Symbol.prototype.valueOf ( )

此方法在被调用时执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。

20.4.3.4.1 ThisSymbolValue ( value )

抽象操作 ThisSymbolValue 接受参数 value(一个 ECMAScript 语言值)并返回一个 包含 Symbol 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是一个 Symbol,返回 value
  2. 如果 value 是一个对象value 有一个 [[SymbolData]] 内部槽,那么
    1. svalue.[[SymbolData]]
    2. 断言s 是一个 Symbol
    3. 返回 s
  3. 抛出 TypeError 异常。

20.4.3.5 Symbol.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法被 ECMAScript 语言操作符调用,以将 Symbol 对象转换为原始值。

当被调用时执行以下步骤:

  1. 返回 ? ThisSymbolValue(this value)。

参数被忽略。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

此方法的 "name" 属性的值是 "[Symbol.toPrimitive]"

20.4.3.6 Symbol.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Symbol"

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

20.4.4 Symbol 实例的属性

Symbol 实例是从 Symbol 原型对象继承属性的 普通对象。Symbol 实例有一个 [[SymbolData]] 内部槽。[[SymbolData]] 内部槽是此 Symbol 对象表示的 Symbol 值。

20.4.5 Symbol 的抽象操作

20.4.5.1 KeyForSymbol ( sym )

抽象操作 KeyForSymbol 接受参数 sym(一个 Symbol)并返回一个字符串或 undefined。如果 symGlobalSymbolRegistry 列表中,将返回用于注册 sym 的字符串。当被调用时执行以下步骤:

  1. 对于 GlobalSymbolRegistry 列表的每个元素 e,执行
    1. 如果 SameValue(e.[[Symbol]], sym) 是 true,返回 e.[[Key]]
  2. 断言GlobalSymbolRegistry 列表当前不包含 sym 的条目。
  3. 返回 undefined

20.5 Error 对象

当运行时错误发生时,Error 对象的实例作为异常被抛出。Error 对象也可以作为用户定义异常类的基对象。

当 ECMAScript 实现检测到运行时错误时,它会抛出在 20.5.5 中定义的 NativeError 对象之一的新实例,或在 20.5.7 中定义的 AggregateError 对象的新实例。

20.5.1 Error 构造器

Error 构造器

  • %Error%
  • 全局对象"Error" 属性的初始值。
  • 当作为函数而不是作为 构造器调用时,创建并初始化一个新的 Error 对象。因此函数调用 Error(…) 等同于具有相同参数的对象创建表达式 new Error(…)
  • 可以用作类定义中 extends 子句的值。打算继承指定的 Error 行为的子类 构造器必须包含一个对 Error 构造器super 调用,以创建和初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.1.1 Error ( message [ , options ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,设 newTarget活动函数对象;否则设 newTarget 为 NewTarget。
  2. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%Error.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. 返回 O

20.5.2 Error 构造器的属性

Error 构造器

20.5.2.1 Error.prototype

Error.prototype 的初始值是 Error 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.3 Error 原型对象的属性

Error 原型对象

  • %Error.prototype%
  • 是一个 普通对象
  • 不是 Error 实例,并且没有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值是 %Object.prototype%

20.5.3.1 Error.prototype.constructor

Error.prototype.constructor 的初始值是 %Error%

20.5.3.2 Error.prototype.message

Error.prototype.message 的初始值是空字符串。

20.5.3.3 Error.prototype.name

Error.prototype.name 的初始值是 "Error"

20.5.3.4 Error.prototype.toString ( )

此方法在被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. name 为 ? Get(O, "name")。
  4. 如果 nameundefined,设 name"Error";否则设 name 为 ? ToString(name)。
  5. msg 为 ? Get(O, "message")。
  6. 如果 msgundefined,设 msg 为空字符串;否则设 msg 为 ? ToString(msg)。
  7. 如果 name 是空字符串,返回 msg
  8. 如果 msg 是空字符串,返回 name
  9. 返回 name、代码单元 0x003A(冒号)、代码单元 0x0020(空格)和 msg字符串连接

20.5.4 Error 实例的属性

Error 实例是从 Error 原型对象继承属性的 普通对象,并有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是在 Object.prototype.toString 中将 Error、AggregateError 和 NativeError 实例标识为 Error 对象。

20.5.5 本标准中使用的原生 Error 类型

当检测到运行时错误时,会抛出下面 NativeError 对象之一或 AggregateError 对象的新实例。所有 NativeError 对象共享相同的结构,如 20.5.6 中所述。

20.5.5.1 EvalError

EvalError 构造器%EvalError%

此异常当前在本规范中未使用。保留此对象是为了与本规范的先前版本兼容。

20.5.5.2 RangeError

RangeError 构造器%RangeError%

表示一个不在允许值集合或范围内的值。

20.5.5.3 ReferenceError

ReferenceError 构造器%ReferenceError%

表示检测到无效引用。

20.5.5.4 SyntaxError

SyntaxError 构造器%SyntaxError%

表示发生了解析错误。

20.5.5.5 TypeError

TypeError 构造器%TypeError%

TypeError 用于表示不成功的操作,当其他 NativeError 对象都不适合表示失败原因时使用。

20.5.5.6 URIError

URIError 构造器%URIError%

表示某个全局 URI 处理函数的使用方式与其定义不兼容。

20.5.6 NativeError 对象结构

这些对象中的每一个都具有下面描述的结构,仅在用作 构造器名称和原型对象的 "name" 属性中使用的名称上有所不同。

对于每个错误对象,定义中对 NativeError 的引用应替换为 20.5.5 中的相应错误对象名称。

20.5.6.1 NativeError 构造器

每个 NativeError 构造器

  • 当作为函数而不是作为 构造器调用时,创建并初始化一个新的 NativeError 对象。将对象作为函数调用等同于使用相同参数将其作为 构造器调用。因此函数调用 NativeError(…) 等同于具有相同参数的对象创建表达式 new NativeError(…)
  • 可以用作类定义中 extends 子句的值。打算继承指定的 NativeError 行为的子类 构造器必须包含一个对 NativeError 构造器super 调用,以创建和初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.6.1.1 NativeError ( message [ , options ] )

每个 NativeError 函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,设 newTarget活动函数对象;否则设 newTarget 为 NewTarget。
  2. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%NativeError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. 返回 O

在步骤 2 中传递的字符串的实际值是 "%EvalError.prototype%""%RangeError.prototype%""%ReferenceError.prototype%""%SyntaxError.prototype%""%TypeError.prototype%""%URIError.prototype%" 中的一个,对应于正在定义的 NativeError 构造器

20.5.6.2 NativeError 构造器的属性

每个 NativeError 构造器

  • 有一个 [[Prototype]] 内部槽,其值是 %Error%
  • 有一个 "name" 属性,其值是字符串值 "NativeError"
  • 有以下属性:

20.5.6.2.1 NativeError.prototype

NativeError.prototype 的初始值是一个 NativeError 原型对象(20.5.6.3)。每个 NativeError 构造器都有一个不同的原型对象。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.6.3 NativeError 原型对象的属性

每个 NativeError 原型对象

  • 是一个 普通对象
  • 不是 Error 实例,并且没有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值是 %Error.prototype%

20.5.6.3.1 NativeError.prototype.constructor

给定 NativeError 构造器的原型的 "constructor" 属性的初始值是 构造器本身。

20.5.6.3.2 NativeError.prototype.message

给定 NativeError 构造器的原型的 "message" 属性的初始值是空字符串。

20.5.6.3.3 NativeError.prototype.name

给定 NativeError 构造器的原型的 "name" 属性的初始值是由 构造器名称(代替 NativeError 使用的名称)组成的字符串值。

20.5.6.4 NativeError 实例的属性

NativeError 实例是从其 NativeError 原型对象继承属性的 普通对象,并有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是被 Object.prototype.toString20.1.3.6)用来标识 Error、AggregateError 或 NativeError 实例。

20.5.7 AggregateError 对象

20.5.7.1 AggregateError 构造器

AggregateError 构造器

  • %AggregateError%
  • 全局对象"AggregateError" 属性的初始值。
  • 当作为函数而不是作为 构造器调用时,创建并初始化一个新的 AggregateError 对象。因此函数调用 AggregateError(…) 等同于具有相同参数的对象创建表达式 new AggregateError(…)
  • 可以用作类定义中 extends 子句的值。打算继承指定的 AggregateError 行为的子类 构造器必须包含一个对 AggregateError 构造器super 调用,以创建和初始化具有 [[ErrorData]] 内部槽的子类实例。

20.5.7.1.1 AggregateError ( errors, message [ , options ] )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 是 undefined,设 newTarget活动函数对象;否则设 newTarget 为 NewTarget。
  2. O 为 ? OrdinaryCreateFromConstructor(newTarget, "%AggregateError.prototype%", « [[ErrorData]] »)。
  3. 如果 message 不是 undefined,那么
    1. msg 为 ? ToString(message)。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "message", msg)。
  4. 执行 ? InstallErrorCause(O, options)。
  5. errorsList 为 ? IteratorToList(? GetIterator(errors, sync))。
  6. 执行 ! DefinePropertyOrThrow(O, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errorsList) })。
  7. 返回 O

20.5.7.2 AggregateError 构造器的属性

AggregateError 构造器

  • 有一个 [[Prototype]] 内部槽,其值是 %Error%
  • 有以下属性:

20.5.7.2.1 AggregateError.prototype

AggregateError.prototype 的初始值是 %AggregateError.prototype%

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

20.5.7.3 AggregateError 原型对象的属性

AggregateError 原型对象

  • %AggregateError.prototype%
  • 是一个 普通对象
  • 不是 Error 实例或 AggregateError 实例,并且没有 [[ErrorData]] 内部槽。
  • 有一个 [[Prototype]] 内部槽,其值是 %Error.prototype%

20.5.7.3.1 AggregateError.prototype.constructor

AggregateError.prototype.constructor 的初始值是 %AggregateError%

20.5.7.3.2 AggregateError.prototype.message

AggregateError.prototype.message 的初始值是空字符串。

20.5.7.3.3 AggregateError.prototype.name

AggregateError.prototype.name 的初始值是 "AggregateError"

20.5.7.4 AggregateError 实例的属性

AggregateError 实例是从其 AggregateError 原型对象继承属性的 普通对象,并有一个值为 undefined[[ErrorData]] 内部槽。[[ErrorData]] 的唯一指定用途是被 Object.prototype.toString20.1.3.6)用来标识 Error、AggregateError 或 NativeError 实例。

20.5.8 Error 对象的抽象操作

20.5.8.1 InstallErrorCause ( O, options )

抽象操作 InstallErrorCause 接受参数 O(一个对象)和 options(一个 ECMAScript 语言值),并返回一个 包含 unused正常完成或一个 抛出完成。当 options 上存在 "cause" 属性时,它用于在 O 上创建一个 "cause" 属性。当被调用时执行以下步骤:

  1. 如果 options 是一个对象且 ? HasProperty(options, "cause") 是 true,那么
    1. cause 为 ? Get(options, "cause")。
    2. 执行 CreateNonEnumerableDataPropertyOrThrow(O, "cause", cause)。
  2. 返回 unused

21 数字和日期

21.1 Number 对象

21.1.1 Number 构造器

Number 构造器

  • %Number%
  • 全局对象"Number" 属性的初始值。
  • 当作为 构造器调用时,创建并初始化一个新的 Number 对象。
  • 当作为函数而不是作为 构造器调用时,执行类型转换。
  • 可以用作类定义中 extends 子句的值。打算继承指定的 Number 行为的子类 构造器必须包含一个对 Number 构造器super 调用,以创建和初始化具有 [[NumberData]] 内部槽的子类实例。

21.1.1.1 Number ( value )

此函数在被调用时执行以下步骤:

  1. 如果 value 存在,那么
    1. prim 为 ? ToNumeric(value)。
    2. 如果 prim 是 BigInt,设 n𝔽((prim))。
    3. 否则,设 nprim
  2. 否则,
    1. n+0𝔽
  3. 如果 NewTarget 是 undefined,返回 n
  4. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Number.prototype%", « [[NumberData]] »)。
  5. 设置 O.[[NumberData]]n
  6. 返回 O

21.1.2 Number 构造器的属性

Number 构造器

21.1.2.1 Number.EPSILON

Number.EPSILON 的值是 1 与大于 1 的可表示为 Number 值的最小值之间差值的幅度的 Number 值,约为 2.2204460492503130808472633361816 × 10-16

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.2 Number.isFinite ( number )

此函数在被调用时执行以下步骤:

  1. 如果 number 不是 Number,返回 false
  2. 如果 number 不是 有限的,返回 false
  3. 否则,返回 true

21.1.2.3 Number.isInteger ( number )

此函数在被调用时执行以下步骤:

  1. 如果 number整数 Number,返回 true
  2. 返回 false

21.1.2.4 Number.isNaN ( number )

此函数在被调用时执行以下步骤:

  1. 如果 number 不是 Number,返回 false
  2. 如果 numberNaN,返回 true
  3. 否则,返回 false

此函数与全局 isNaN 函数(19.2.3)的不同之处在于,它在确定参数是否为 NaN 之前不会将其转换为 Number。

21.1.2.5 Number.isSafeInteger ( number )

当且仅当 nNumber 值不是任何其他 整数Number 值时,整数 n 是"安全整数"。

此函数在被调用时执行以下步骤:

  1. 如果 number整数 Number,那么
    1. 如果 abs((number)) ≤ 253 - 1,返回 true
  2. 返回 false

21.1.2.6 Number.MAX_SAFE_INTEGER

由于 IEEE 754-2019 精度限制所必需的舍入行为,每个大于 Number.MAX_SAFE_INTEGER整数Number 值都与至少一个其他 整数共享。因此,这些大幅度的 整数不是 安全的,并且不保证能准确表示为 Number 值,甚至不保证彼此可区分。例如,90071992547409929007199254740993 都计算为 Number 值 9007199254740992𝔽

Number.MAX_SAFE_INTEGER 的值是 9007199254740991𝔽𝔽(253 - 1))。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.7 Number.MAX_VALUE

Number.MAX_VALUE 的值是 Number 类型的最大正 有限值,约为 1.7976931348623157 × 10308

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.8 Number.MIN_SAFE_INTEGER

由于 IEEE 754-2019 精度限制所必需的舍入行为,每个小于 Number.MIN_SAFE_INTEGER整数Number 值都与至少一个其他 整数共享。因此,这些大幅度的 整数不是 安全的,并且不保证能准确表示为 Number 值,甚至不保证彼此可区分。例如,-9007199254740992-9007199254740993 都计算为 Number 值 -9007199254740992𝔽

Number.MIN_SAFE_INTEGER 的值是 -9007199254740991𝔽𝔽(-(253 - 1)))。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.9 Number.MIN_VALUE

Number.MIN_VALUE 的值是 Number 类型的最小正值,约为 5 × 10-324

IEEE 754-2019 双精度二进制表示中,最小可能值是非正规化数。如果实现不支持非正规化值,Number.MIN_VALUE 的值必须是实现实际能表示的最小非零正值。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.10 Number.NaN

Number.NaN 的值是 NaN

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.11 Number.NEGATIVE_INFINITY

Number.NEGATIVE_INFINITY 的值是 -∞𝔽

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.12 Number.parseFloat ( string )

"parseFloat" 属性的初始值是 %parseFloat%

21.1.2.13 Number.parseInt ( string, radix )

"parseInt" 属性的初始值是 %parseInt%

21.1.2.14 Number.POSITIVE_INFINITY

Number.POSITIVE_INFINITY 的值是 +∞𝔽

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.2.15 Number.prototype

Number.prototype 的初始值是 Number 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.1.3 Number 原型对象的属性

Number 原型对象

  • %Number.prototype%
  • 是一个 普通对象
  • 本身是一个 Number 对象;它有一个 [[NumberData]] 内部槽,值为 +0𝔽
  • 有一个 [[Prototype]] 内部槽,其值是 %Object.prototype%

除非明确说明,下面定义的 Number 原型对象的方法不是通用的,传递给它们的 this 值必须是 Number 值或具有已初始化为 Number 值的 [[NumberData]] 内部槽的对象。

方法规范中的短语"此 Number 值"是指通过将方法调用的 this 值作为参数调用抽象操作 ThisNumberValue 返回的结果。

21.1.3.1 Number.prototype.constructor

Number.prototype.constructor 的初始值是 %Number%

21.1.3.2 Number.prototype.toExponential ( fractionDigits )

此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,它包含尽可能多的有效数字位数以唯一地指定 Number(就像在 ToString 中一样,除了在这种情况下 Number 总是以指数记法输出)。

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. f 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,那么 f 是 0。
  4. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  5. 如果 f < 0 或 f > 100,抛出 RangeError 异常。
  6. 设置 x(x)。
  7. s 为空字符串。
  8. 如果 x < 0,那么
    1. 设置 s"-"
    2. 设置 x 为 -x
  9. 如果 x = 0,那么
    1. m 为由 f + 1 个代码单元 0x0030(数字零)组成的字符串值。
    2. e 为 0。
  10. 否则,
    1. 如果 fractionDigits 不是 undefined,那么
      1. en整数,使得 10fn < 10f + 1n × 10e - f - x 尽可能接近零。如果有两组这样的 en,选择使 n × 10e - f 更大的 en
    2. 否则,
      1. enff整数,使得 ff ≥ 0,10ffn < 10ff + 1𝔽(n × 10e - ff) 是 𝔽(x), 且 ff 尽可能小。注意 n 的十进制表示有 ff + 1 位数字,n 不能被 10 整除,且 n 的最低有效位不一定由这些条件唯一确定。
      2. 设置 fff
    3. m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
  11. 如果 f ≠ 0,那么
    1. am 的第一个代码单元。
    2. bm 的其他 f 个代码单元。
    3. 设置 ma"."b字符串连接
  12. 如果 e = 0,那么
    1. c"+"
    2. d"0"
  13. 否则,
    1. 如果 e > 0,那么
      1. c"+"
    2. 否则,
      1. 断言e < 0。
      2. c"-"
      3. 设置 e 为 -e
    3. d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
  14. 设置 mm"e"cd字符串连接
  15. 返回 sm字符串连接

对于提供比上述规则要求更准确转换的实现,建议将以下步骤 10.b.i 的替代版本用作指导:

  1. enf整数,使得 f ≥ 0, 10fn < 10f + 1𝔽(n × 10e - f) 是 𝔽(x),且 f 尽可能小。如果 n 有多种可能性,选择使 𝔽(n × 10e - f) 在值上最接近 𝔽(x) 的 n 值。如果有两个这样的可能 n 值,选择偶数的那个。

21.1.3.3 Number.prototype.toFixed ( fractionDigits )

注 1

此方法返回一个字符串,包含以十进制定点记法表示的此 Number 值,小数点后有 fractionDigits 位数字。如果 fractionDigitsundefined,假定为 0。

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. f 为 ? ToIntegerOrInfinity(fractionDigits)。
  3. 断言:如果 fractionDigitsundefined,那么 f 是 0。
  4. 如果 f 不是 有限的,抛出 RangeError 异常。
  5. 如果 f < 0 或 f > 100,抛出 RangeError 异常。
  6. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  7. 设置 x(x)。
  8. s 为空字符串。
  9. 如果 x < 0,那么
    1. 设置 s"-"
    2. 设置 x 为 -x
  10. 如果 x ≥ 1021,那么
    1. m 为 ! ToString(𝔽(x))。
  11. 否则,
    1. n 为一个 整数,使得 n / 10f - x 尽可能接近零。如果有两个这样的 n,选择较大的 n
    2. 如果 n = 0,设 m"0"。否则,设 m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
    3. 如果 f ≠ 0,那么
      1. km 的长度。
      2. 如果 kf,那么
        1. z 为由 f + 1 - k 个代码单元 0x0030(数字零)组成的字符串值。
        2. 设置 mzm字符串连接
        3. 设置 kf + 1。
      3. am 的前 k - f 个代码单元。
      4. bm 的其他 f 个代码单元。
      5. 设置 ma"."b字符串连接
  12. 返回 sm字符串连接
注 2

对于某些值,toFixed 的输出可能比 toString 更精确,因为 toString 只打印足够的有效数字来区分该数字与相邻的 Number 值。例如,

(1000000000000000128).toString() 返回 "1000000000000000100",而
(1000000000000000128).toFixed(0) 返回 "1000000000000000128"

21.1.3.4 Number.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法产生一个字符串值,该值表示根据 宿主环境当前区域设置的约定格式化的此 Number 值。此方法是 实现定义的,允许(但不鼓励)它返回与 toString 相同的内容。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

21.1.3.5 Number.prototype.toPrecision ( precision )

此方法返回一个字符串,包含以十进制指数记法表示的此 Number 值,有效数字的小数点前有一位数字,小数点后有 precision - 1 位数字,或者以十进制定点记法表示,有 precision 个有效数字。如果 precisionundefined,它改为调用 ToString

当被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. 如果 precisionundefined,返回 ! ToString(x)。
  3. p 为 ? ToIntegerOrInfinity(precision)。
  4. 如果 x 不是 有限的,返回 Number::toString(x, 10)。
  5. 如果 p < 1 或 p > 100,抛出 RangeError 异常。
  6. 设置 x(x)。
  7. s 为空字符串。
  8. 如果 x < 0,那么
    1. 设置 s 为代码单元 0x002D(连字符减号)。
    2. 设置 x 为 -x
  9. 如果 x = 0,那么
    1. m 为由 p 个代码单元 0x0030(数字零)组成的字符串值。
    2. e 为 0。
  10. 否则,
    1. en整数,使得 10p - 1n < 10pn × 10e - p + 1 - x 尽可能接近零。如果有两组这样的 en,选择使 n × 10e - p + 1 更大的 en
    2. m 为由 n 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
    3. 如果 e < -6 或 ep,那么
      1. 断言e ≠ 0。
      2. 如果 p ≠ 1,那么
        1. am 的第一个代码单元。
        2. bm 的其他 p - 1 个代码单元。
        3. 设置 ma"."b字符串连接
      3. 如果 e > 0,那么
        1. c 为代码单元 0x002B(加号)。
      4. 否则,
        1. 断言e < 0。
        2. c 为代码单元 0x002D(连字符减号)。
        3. 设置 e 为 -e
      5. d 为由 e 的十进制表示的数字组成的字符串值(按顺序,没有前导零)。
      6. 返回 sm、代码单元 0x0065(拉丁小写字母 E)、cd字符串连接
  11. 如果 e = p - 1,返回 sm字符串连接
  12. 如果 e ≥ 0,那么
    1. 设置 mm 的前 e + 1 个代码单元、代码单元 0x002E(句号)和 m 的其余 p - (e + 1) 个代码单元的 字符串连接
  13. 否则,
    1. 设置 m 为代码单元 0x0030(数字零)、代码单元 0x002E(句号)、-(e + 1) 个代码单元 0x0030(数字零)和字符串 m字符串连接
  14. 返回 sm字符串连接

21.1.3.6 Number.prototype.toString ( [ radix ] )

可选的 radix 应该是在从 2𝔽36𝔽包含区间内的 整数 Number 值。如果 radixundefined,那么使用 10𝔽 作为 radix 的值。

此方法在被调用时执行以下步骤:

  1. x 为 ? ThisNumberValue(this value)。
  2. 如果 radixundefined,设 radixMV 为 10。
  3. 否则,设 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在从 2 到 36 的 包含区间内,抛出 RangeError 异常。
  5. 返回 Number::toString(x, radixMV)。

此方法不是通用的;如果其 this不是 Number 或 Number 对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。

此方法的 "length" 属性是 1𝔽

21.1.3.7 Number.prototype.valueOf ( )

  1. 返回 ? ThisNumberValue(this value)。

21.1.3.7.1 ThisNumberValue ( value )

抽象操作 ThisNumberValue 接受参数 value(一个 ECMAScript 语言值),并返回一个 包含 Number 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是 Number,返回 value
  2. 如果 value 是对象value[[NumberData]] 内部槽,那么
    1. nvalue.[[NumberData]]
    2. 断言n 是 Number
    3. 返回 n
  3. 抛出 TypeError 异常。

21.1.4 Number 实例的属性

Number 实例是从 Number 原型对象继承属性的 普通对象。Number 实例还有一个 [[NumberData]] 内部槽。[[NumberData]] 内部槽是此 Number 对象表示的 Number 值。

21.2 BigInt 对象

21.2.1 BigInt 构造器

BigInt 构造器

  • %BigInt%
  • 全局对象"BigInt" 属性的初始值。
  • 当作为函数而不是作为 构造器调用时,执行类型转换。
  • 不打算与 new 操作符一起使用或被子类化。它可以用作类定义中 extends 子句的值,但对 BigInt 构造器super 调用将导致异常。

21.2.1.1 BigInt ( value )

此函数在被调用时执行以下步骤:

  1. 如果 NewTarget 不是 undefined,抛出 TypeError 异常。
  2. prim 为 ? ToPrimitive(value, number)。
  3. 如果 prim 是 Number,返回 ? NumberToBigInt(prim)。
  4. 否则,返回 ? ToBigInt(prim)。

21.2.1.1.1 NumberToBigInt ( number )

抽象操作 NumberToBigInt 接受参数 number(一个 Number),并返回一个 包含 BigInt 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 number 不是 整数 Number, 抛出 RangeError 异常。
  2. 返回 ((number))。

21.2.2 BigInt 构造器的属性

BigInt 构造器

21.2.2.1 BigInt.asIntN ( bits, bigint )

此函数在被调用时执行以下步骤:

  1. 设置 bits 为 ? ToIndex(bits)。
  2. 设置 bigint 为 ? ToBigInt(bigint)。
  3. mod(bigint) modulo 2bits
  4. 如果 mod ≥ 2bits - 1,返回 (mod - 2bits);否则,返回 (mod)。

21.2.2.2 BigInt.asUintN ( bits, bigint )

此函数在被调用时执行以下步骤:

  1. 设置 bits 为 ? ToIndex(bits)。
  2. 设置 bigint 为 ? ToBigInt(bigint)。
  3. 返回 ((bigint) modulo 2bits)。

21.2.2.3 BigInt.prototype

BigInt.prototype 的初始值是 BigInt 原型对象

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.2.3 BigInt 原型对象的属性

BigInt 原型对象

方法规范中的短语"此 BigInt 值"是指通过将方法调用的 this 值作为参数调用抽象操作 ThisBigIntValue 返回的结果。

21.2.3.1 BigInt.prototype.constructor

BigInt.prototype.constructor 的初始值是 %BigInt%

21.2.3.2 BigInt.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范中的规定实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用此方法的以下规范:

此方法产生一个字符串值,该值表示根据 宿主环境当前区域设置的约定格式化的此 BigInt 值。此方法是 实现定义的,允许(但不鼓励)它返回与 toString 相同的内容。

此方法的可选参数的含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于任何其他用途。

21.2.3.3 BigInt.prototype.toString ( [ radix ] )

可选的 radix 应该是在从 2𝔽36𝔽包含区间内的 整数 Number 值。如果 radixundefined,那么使用 10𝔽 作为 radix 的值。

此方法在被调用时执行以下步骤:

  1. x 为 ? ThisBigIntValue(this value)。
  2. 如果 radixundefined,设 radixMV 为 10。
  3. 否则,设 radixMV 为 ? ToIntegerOrInfinity(radix)。
  4. 如果 radixMV 不在从 2 到 36 的 包含区间内,抛出 RangeError 异常。
  5. 返回 BigInt::toString(x, radixMV)。

此方法不是通用的;如果其 this不是 BigInt 或 BigInt 对象,它会抛出 TypeError 异常。因此,它不能转移到其他类型的对象上用作方法。

21.2.3.4 BigInt.prototype.valueOf ( )

  1. 返回 ? ThisBigIntValue(this value)。

21.2.3.4.1 ThisBigIntValue ( value )

抽象操作 ThisBigIntValue 接受参数 value(一个 ECMAScript 语言值),并返回一个 包含 BigInt 的 正常完成或一个 抛出完成。当被调用时执行以下步骤:

  1. 如果 value 是 BigInt,返回 value
  2. 如果 value 是对象value[[BigIntData]] 内部槽,那么
    1. 断言value.[[BigIntData]] 是 BigInt
    2. 返回 value.[[BigIntData]]
  3. 抛出 TypeError 异常。

21.2.3.5 BigInt.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "BigInt"

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.2.4 BigInt 实例的属性

BigInt 实例是从 BigInt 原型对象继承属性的 普通对象。BigInt 实例还有一个 [[BigIntData]] 内部槽。[[BigIntData]] 内部槽是此 BigInt 对象表示的 BigInt 值。

21.3 Math 对象

Math 对象:

  • %Math%
  • 全局对象"Math" 属性的初始值。
  • 是一个 普通对象
  • 有一个 [[Prototype]] 内部槽,其值是 %Object.prototype%
  • 不是 函数对象
  • 没有 [[Construct]] 内部方法;它不能与 new 操作符一起用作 构造器
  • 没有 [[Call]] 内部方法;它不能作为函数被调用。

在此规范中,短语"xNumber 值"具有在 6.1.6.1 中定义的技术含义。

21.3.1 Math 对象的值属性

21.3.1.1 Math.E

e(自然对数的底)的 Number 值,约为 2.7182818284590452354。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.2 Math.LN10

10 的自然对数的 Number 值,约为 2.302585092994046。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.3 Math.LN2

2 的自然对数的 Number 值,约为 0.6931471805599453。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.4 Math.LOG10E

e(自然对数的底)的以 10 为底的对数的 Number 值;此值约为 0.4342944819032518。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.LOG10E 的值约为 Math.LN10 值的倒数。

21.3.1.5 Math.LOG2E

e(自然对数的底)的以 2 为底的对数的 Number 值;此值约为 1.4426950408889634。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.LOG2E 的值约为 Math.LN2 值的倒数。

21.3.1.6 Math.PI

π(圆的周长与其直径的比值)的 Number 值,约为 3.1415926535897932。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.7 Math.SQRT1_2

½ 的平方根的 Number 值,约为 0.7071067811865476。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

Math.SQRT1_2 的值约为 Math.SQRT2 值的倒数。

21.3.1.8 Math.SQRT2

2 的平方根的 Number 值,约为 1.4142135623730951。

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.3.1.9 Math [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串值 "Math"

此属性有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

21.3.2 Math 对象的函数属性

函数 acosacoshasinasinhatanatanhatan2cbrtcoscoshexpexpm1hypotloglog1plog2log10powrandomsinsinhtantanh 的行为在此处未被精确指定,除了要求对表示感兴趣的边界情况的某些参数值有特定结果。对于其他参数值,这些函数意图计算熟悉的数学函数结果的近似值,但在近似算法的选择上允许一定的灵活性。总的意图是实现者应该能够在给定硬件平台上为 ECMAScript 使用与该平台上 C 程序员可用的相同数学库。

虽然算法的选择留给实现,但建议(但不是本标准规定的)实现使用 IEEE 754-2019 算术的近似算法,这些算法包含在 fdlibm 中,这是来自 Sun Microsystems 的可自由分发的数学库(http://www.netlib.org/fdlibm)。

21.3.2.1 Math.abs ( x )

此函数返回 x 的绝对值;结果与 x 具有相同的量级但符号为正。

当被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n-0𝔽,返回 +0𝔽
  4. 如果 n-∞𝔽,返回 +∞𝔽
  5. 如果 n < -0𝔽,返回 -n
  6. 返回 n

21.3.2.2 Math.acos ( x )

此函数返回 x 的反余弦值。结果以弧度表示,在从 +0𝔽𝔽(π) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaNn > 1𝔽,或 n < -1𝔽,返回 NaN
  3. 如果 n1𝔽,返回 +0𝔽
  4. 返回一个实现近似的 Number 值,表示 (n) 的反余弦值。

21.3.2.3 Math.acosh ( x )

此函数返回 x 的反双曲余弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n < 1𝔽,返回 NaN
  5. 返回一个实现近似的 Number 值,表示 (n) 的反双曲余弦值。

21.3.2.4 Math.asin ( x )

此函数返回 x 的反正弦值。结果以弧度表示,在从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n > 1𝔽n < -1𝔽,返回 NaN
  4. 返回一个实现近似的 Number 值,表示 (n) 的反正弦值。

21.3.2.5 Math.asinh ( x )

此函数返回 x 的反双曲正弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的反双曲正弦值。

21.3.2.6 Math.atan ( x )

此函数返回 x 的反正切值。结果以弧度表示,在从 𝔽(-π / 2) 到 𝔽(π / 2) 的闭区间内。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回一个实现近似的 Number 值,表示 π / 2。
  4. 如果 n-∞𝔽,返回一个实现近似的 Number 值,表示 -π / 2。
  5. 返回一个实现近似的 Number 值,表示 (n) 的反正切值。

21.3.2.7 Math.atanh ( x )

此函数返回 x 的反双曲正切值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n > 1𝔽n < -1𝔽,返回 NaN
  4. 如果 n1𝔽,返回 +∞𝔽
  5. 如果 n-1𝔽,返回 -∞𝔽
  6. 返回一个实现近似的 Number 值,表示 (n) 的反双曲正切值。

21.3.2.8 Math.atan2 ( y, x )

此函数返回参数 yx 的商 y / x 的反正切值,其中 yx 的符号用于确定 结果的象限。请注意,对于双参数反正切函数,参数名为 y 的位于第一位而参数名为 x 的位于第二位是有意的和传统的。结果以弧度表示,在从 -π 到 +π 的闭区间内。

它在被调用时执行以下步骤:

  1. ny 为 ? ToNumber(y)。
  2. nx 为 ? ToNumber(x)。
  3. 如果 nyNaNnxNaN,返回 NaN
  4. 如果 ny+∞𝔽,则
    1. 如果 nx+∞𝔽,返回一个实现近似的 Number 值,表示 π / 4。
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 3π / 4。
    3. 返回一个实现近似的 Number 值,表示 π / 2。
  5. 如果 ny-∞𝔽,则
    1. 如果 nx+∞𝔽,返回一个实现近似的 Number 值,表示 -π / 4。
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 -3π / 4。
    3. 返回一个实现近似的 Number 值,表示 -π / 2。
  6. 如果 ny+0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 +0𝔽
    2. 返回一个实现近似的 Number 值,表示 π。
  7. 如果 ny-0𝔽,则
    1. 如果 nx > +0𝔽nx+0𝔽,返回 -0𝔽
    2. 返回一个实现近似的 Number 值,表示 -π。
  8. 断言ny有限的且既不是 +0𝔽 也不是 -0𝔽
  9. 如果 ny > +0𝔽,则
    1. 如果 nx+∞𝔽,返回 +0𝔽
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 π。
    3. 如果 nx+0𝔽-0𝔽,返回一个实现近似的 Number 值,表示 π / 2。
  10. 如果 ny < -0𝔽,则
    1. 如果 nx+∞𝔽,返回 -0𝔽
    2. 如果 nx-∞𝔽,返回一个实现近似的 Number 值,表示 -π。
    3. 如果 nx+0𝔽-0𝔽,返回一个实现近似的 Number 值,表示 -π / 2。
  11. 断言nx有限的且既不是 +0𝔽 也不是 -0𝔽
  12. rabs((ny) / (nx)) 的反正切值。
  13. 如果 nx < -0𝔽,则
    1. 如果 ny > +0𝔽,设 r 为 π - r
    2. 否则,设 r 为 -π + r
  14. 否则,
    1. 如果 ny < -0𝔽,设 r 为 -r
  15. 返回一个实现近似的 Number 值,表示 r

21.3.2.9 Math.cbrt ( x )

此函数返回 x 的立方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的立方根。

21.3.2.10 Math.ceil ( x )

此函数返回不小于 x 的最小(最接近 -∞)整数 Number 值。如果 x 已经是一个整数 Number,结果就是 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 如果 n < -0𝔽n > -1𝔽,返回 -0𝔽
  4. 如果 n 是一个整数 Number,返回 n
  5. 返回不小于 n 的最小(最接近 -∞)整数 Number 值。
注意

Math.ceil(x) 的值与 -Math.floor(-x) 的值相同。

21.3.2.11 Math.clz32 ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToUint32(x)。
  2. pn 的无符号 32 位二进制表示中前导零位的数量。
  3. 返回 𝔽(p)。
注意

如果 n+0𝔽-0𝔽,此方法返回 32𝔽。如果 n 的 32 位二进制编码的最高有效位是 1,此方法返回 +0𝔽

21.3.2.12 Math.cos ( x )

此函数返回 x 的余弦值。参数以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的,返回 NaN
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 返回一个实现近似的 Number 值,表示 (n) 的余弦值。

21.3.2.13 Math.cosh ( x )

此函数返回 x 的双曲余弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+∞𝔽-∞𝔽,返回 +∞𝔽
  4. 如果 n+0𝔽-0𝔽,返回 1𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的双曲余弦值。
注意

Math.cosh(x) 的值与 (Math.exp(x) + Math.exp(-x)) / 2 的值相同。

21.3.2.14 Math.exp ( x )

此函数返回 x 的指数函数(ex 次幂,其中 e 是自然对数的底)。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n+0𝔽-0𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 +0𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的指数函数。

21.3.2.15 Math.expm1 ( x )

此函数返回从 x 的指数函数(ex 次幂,其中 e 是自然对数的底)中减去 1 的结果。该结果以一种即使当 x 的值接近 0 时也很准确的方式计算。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽,或 +∞𝔽 之一,返回 n
  3. 如果 n-∞𝔽,返回 -1𝔽
  4. exp(n) 的指数函数。
  5. 返回一个实现近似的 Number 值,表示 exp - 1。

21.3.2.16 Math.floor ( x )

此函数返回不大于 x 的最大(最接近 +∞)整数 Number 值。如果 x 已经是一个整数 Number,结果就是 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 如果 n < 1𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n 是一个整数 Number,返回 n
  5. 返回不大于 n 的最大(最接近 +∞)整数 Number 值。
注意

Math.floor(x) 的值与 -Math.ceil(-x) 的值相同。

21.3.2.17 Math.fround ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+0𝔽-0𝔽+∞𝔽,或 -∞𝔽 之一,返回 n
  4. n32 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary32 格式的结果。
  5. n64 为将 n32 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回对应于 n64 的 ECMAScript Number 值。

21.3.2.18 Math.f16round ( x )

此函数在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN,返回 NaN
  3. 如果 n+0𝔽-0𝔽+∞𝔽,或 -∞𝔽 之一,返回 n
  4. n16 为使用 roundTiesToEven 模式将 n 转换为 IEEE 754-2019 binary16 格式的结果。
  5. n64 为将 n16 转换为 IEEE 754-2019 binary64 格式的结果。
  6. 返回对应于 n64 的 ECMAScript Number 值。
注意

此操作与先转换为 binary32 再转换为 binary16 是不同的,因为可能存在双重舍入:例如,考虑数字 k = 1.00048828125000022204𝔽,对于它,Math.f16round(k) 是 1.0009765625𝔽,但 Math.f16round(Math.fround(k)) 是 1𝔽

并非所有平台都提供从 binary64 转换为 binary16 的原生支持。有各种库可以提供此功能,包括 MIT 许可的 half 库。或者,可以首先在 roundTiesToEven 下从 binary64 转换为 binary32,然后检查结果是否可能导致不正确的双重舍入。可能导致问题的情况可以通过调整 binary32 值的尾数来明确处理,使其成为在 roundTiesToOdd 下执行初始转换时会产生的值。然后在 roundTiesToEven 下将调整后的值转换为 binary16 就会产生正确的值。

21.3.2.19 Math.hypot ( ...args )

给定零个或多个参数,此函数返回其参数的平方和的平方根。

它在被调用时执行以下步骤:

  1. coerced 为一个新的空列表
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 追加到 coerced
  3. 对于 coerced 的每个元素 number,执行
    1. 如果 number+∞𝔽-∞𝔽,返回 +∞𝔽
  4. onlyZerotrue
  5. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number 既不是 +0𝔽 也不是 -0𝔽,设 onlyZerofalse
  6. 如果 onlyZerotrue,返回 +0𝔽
  7. 返回一个实现近似的 Number 值,表示 coerced 元素的数学值的平方和的平方根。

此函数的 "length" 属性是 2𝔽

注意

实现应当注意避免当此函数以两个或更多参数调用时,在朴素实现中容易发生的溢出和下溢导致的精度损失。

21.3.2.20 Math.imul ( x, y )

此函数在被调用时执行以下步骤:

  1. a(? ToUint32(x))。
  2. b(? ToUint32(y))。
  3. product 为 (a × b) 232
  4. 如果 product ≥ 231,返回 𝔽(product - 232);否则返回 𝔽(product)。

21.3.2.21 Math.log ( x )

此函数返回 x 的自然对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回一个实现近似的 Number 值,表示 (n) 的自然对数。

21.3.2.22 Math.log1p ( x )

此函数返回 1 + x 的自然对数。该结果以一种即使当 x 的值接近零时也很准确的方式计算。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽,或 +∞𝔽 之一,返回 n
  3. 如果 n-1𝔽,返回 -∞𝔽
  4. 如果 n < -1𝔽,返回 NaN
  5. 返回一个实现近似的 Number 值,表示 1 + (n) 的自然对数。

21.3.2.23 Math.log10 ( x )

此函数返回 x 的以 10 为底的对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回一个实现近似的 Number 值,表示 (n) 的以 10 为底的对数。

21.3.2.24 Math.log2 ( x )

此函数返回 x 的以 2 为底的对数。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+∞𝔽,返回 n
  3. 如果 n1𝔽,返回 +0𝔽
  4. 如果 n+0𝔽-0𝔽,返回 -∞𝔽
  5. 如果 n < -0𝔽,返回 NaN
  6. 返回一个实现近似的 Number 值,表示 (n) 的以 2 为底的对数。

21.3.2.25 Math.max ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最大值。

它在被调用时执行以下步骤:

  1. coerced 为一个新的空列表
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 追加到 coerced
  3. highest-∞𝔽
  4. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number+0𝔽highest-0𝔽,设 highest+0𝔽
    3. 如果 number > highest,设 highestnumber
  5. 返回 highest
注意

确定最大值的值比较使用 IsLessThan 算法完成,但是 +0𝔽 被认为大于 -0𝔽

此函数的 "length" 属性是 2𝔽

21.3.2.26 Math.min ( ...args )

给定零个或多个参数,此函数对每个参数调用 ToNumber 并返回结果值中的最小值。

它在被调用时执行以下步骤:

  1. coerced 为一个新的空列表
  2. 对于 args 的每个元素 arg,执行
    1. n 为 ? ToNumber(arg)。
    2. n 追加到 coerced
  3. lowest+∞𝔽
  4. 对于 coerced 的每个元素 number,执行
    1. 如果 numberNaN,返回 NaN
    2. 如果 number-0𝔽lowest+0𝔽,设 lowest-0𝔽
    3. 如果 number < lowest,设 lowestnumber
  5. 返回 lowest
注意

确定最小值的值比较使用 IsLessThan 算法完成,但是 +0𝔽 被认为大于 -0𝔽

此函数的 "length" 属性是 2𝔽

21.3.2.27 Math.pow ( base, exponent )

此函数在被调用时执行以下步骤:

  1. base 为 ? ToNumber(base)。
  2. exponent 为 ? ToNumber(exponent)。
  3. 返回 Number::exponentiate(base, exponent)。

21.3.2.28 Math.random ( )

此函数返回一个具有正号的 Number 值,大于或等于 +0𝔽 但严格小于 1𝔽, 使用实现定义的算法或策略随机或伪随机选择,在该范围内具有近似均匀分布。

为不同领域创建的每个 Math.random 函数必须从连续调用中产生不同的值序列。

21.3.2.29 Math.round ( x )

此函数返回最接近 x 且为整数的 Number 值。如果两个整数 Numberx 的距离相等,则结果是更接近 +∞ 的 Number 值。如果 x 已经是整数,结果就是 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n 是一个整数 Number,返回 n
  3. 如果 n < 0.5𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n < -0𝔽n-0.5𝔽,返回 -0𝔽
  5. 返回最接近 n整数 Number,在平局的情况下优选更接近 +∞ 的 Number。
注意 1

Math.round(3.5) 返回 4,但 Math.round(-3.5) 返回 -3。

注意 2

Math.round(x) 的值并不总是与 Math.floor(x + 0.5) 的值相同。当 x-0𝔽x 小于 -0𝔽 但大于或等于 -0.5𝔽 时,Math.round(x) 返回 -0𝔽,但 Math.floor(x + 0.5) 返回 +0𝔽Math.round(x) 也可能因为计算 x + 0.5 时的内部舍入而与 Math.floor(x + 0.5) 的值不同。

21.3.2.30 Math.sign ( x )

此函数返回 x 的符号,指示 x 是正数、负数还是零。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n < -0𝔽,返回 -1𝔽
  4. 返回 1𝔽

21.3.2.31 Math.sin ( x )

此函数返回 x 的正弦值。参数以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽-∞𝔽,返回 NaN
  4. 返回一个实现近似的 Number 值,表示 (n) 的正弦值。

21.3.2.32 Math.sinh ( x )

此函数返回 x 的双曲正弦值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 返回一个实现近似的 Number 值,表示 (n) 的双曲正弦值。
注意

Math.sinh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / 2 的值相同。

21.3.2.33 Math.sqrt ( x )

此函数返回 x 的平方根。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽-0𝔽,或 +∞𝔽 之一,返回 n
  3. 如果 n < -0𝔽,返回 NaN
  4. 返回 𝔽((n) 的平方根)。

21.3.2.34 Math.tan ( x )

此函数返回 x 的正切值。参数以弧度表示。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽-∞𝔽,返回 NaN
  4. 返回一个实现近似的 Number 值,表示 (n) 的正切值。

21.3.2.35 Math.tanh ( x )

此函数返回 x 的双曲正切值。

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 nNaN+0𝔽,或 -0𝔽 之一,返回 n
  3. 如果 n+∞𝔽,返回 1𝔽
  4. 如果 n-∞𝔽,返回 -1𝔽
  5. 返回一个实现近似的 Number 值,表示 (n) 的双曲正切值。
注意

Math.tanh(x) 的值与 (Math.exp(x) - Math.exp(-x)) / (Math.exp(x) + Math.exp(-x)) 的值相同。

21.3.2.36 Math.trunc ( x )

此函数返回数字 x 的整数部分,移除任何小数位。如果 x 已经是整数,结果就是 x

它在被调用时执行以下步骤:

  1. n 为 ? ToNumber(x)。
  2. 如果 n 不是有限的n+0𝔽-0𝔽,返回 n
  3. 如果 n < 1𝔽n > +0𝔽,返回 +0𝔽
  4. 如果 n < -0𝔽n > -1𝔽,返回 -0𝔽
  5. 返回最接近 n 且朝向 +0𝔽 方向的整数 Number

21.4 Date 对象

21.4.1 Date 对象概述和抽象操作的定义

以下抽象操作时间值(在 21.4.1.1 中定义)进行操作。注意,在任何情况下,如果这些函数的任何参数是 NaN,结果将是 NaN

21.4.1.1 时间值和时间范围

ECMAScript 中的时间测量类似于 POSIX 中的时间测量,特别是共享以前推格里高利历为基础的定义,以 1970 年 1 月 1 日 UTC 午夜开始为纪元,并且将每一天计算为恰好 86,400 秒(每秒为 1000 毫秒)。

ECMAScript 时间值是一个 Number,要么是一个有限整数 Number,表示精确到毫秒的时间瞬间,要么是 NaN,表示没有特定的时间瞬间。是 24 × 60 × 60 × 1000 = 86,400,000 的倍数(即,对于某个整数 d 为 86,400,000 × d)的时间值表示在纪元之后 d 个完整 UTC 天(负 d 表示在纪元之前)的 UTC 天开始时的瞬间。任何其他有限时间值 t 相对于最大的前导时间值 s(其为这样的倍数)定义,并表示在与 s 相同的 UTC 天内但在它之后 (t - s) 毫秒发生的瞬间。

时间值不考虑 UTC 闰秒——没有时间值表示正闰秒内的瞬间,并且有时间值表示被负闰秒从 UTC 时间线中移除的瞬间。然而,时间值的定义仍然产生与 UTC 的分段对齐,仅在闰秒边界处有不连续性,在闰秒之外没有差异。

Number 可以精确表示从 -9,007,199,254,740,992 到 9,007,199,254,740,992 的所有整数21.1.2.821.1.2.6)。时间值支持稍小的范围,从 -8,640,000,000,000,000 到 8,640,000,000,000,000 毫秒。这产生了一个支持的时间值范围,恰好相对于 1970 年 1 月 1 日 UTC 午夜为 -100,000,000 天到 100,000,000 天。

1970 年 1 月 1 日 UTC 午夜开始的确切时刻由时间值 +0𝔽 表示。

注意

在前推格里高利历中,闰年恰好是那些既能被 4 整除,又能被 400 整除或不能被 100 整除的年份。

前推格里高利历的 400 年周期包含 97 个闰年。这产生平均每年 365.2425 天,即 31,556,952,000 毫秒。因此,Number 能以毫秒精度精确表示的最大范围大约是相对于 1970 年的 -285,426 到 285,426 年。本节中指定的时间值支持的较小范围大约是相对于 1970 年的 -273,790 到 273,790 年。

21.4.1.2 时间相关常量

这些常量被以下部分的算法引用。

HoursPerDay = 24
MinutesPerHour = 60
SecondsPerMinute = 60
msPerSecond = 1000𝔽
msPerMinute = 60000𝔽 = msPerSecond × 𝔽(SecondsPerMinute)
msPerHour = 3600000𝔽 = msPerMinute × 𝔽(MinutesPerHour)
msPerDay = 86400000𝔽 = msPerHour × 𝔽(HoursPerDay)

21.4.1.3 Day ( t )

抽象操作 Day 接受参数 t(一个有限时间值)并返回一个整数 Number。它返回 t 所在天的天数。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerDay)))。

21.4.1.4 TimeWithinDay ( t )

抽象操作 TimeWithinDay 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽(包含)到 msPerDay(不包含)的区间内的整数 Number。它返回自 t 所在天开始以来的毫秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽((t) (msPerDay))。

21.4.1.5 DaysInYear ( y )

抽象操作 DaysInYear 接受参数 y(一个整数 Number)并返回 365𝔽366𝔽。它返回年份 y 中的天数。闰年有 366 天;所有其他年份有 365 天。它在被调用时执行以下步骤:

  1. ry(y)。
  2. 如果 (ry 400) = 0,返回 366𝔽
  3. 如果 (ry 100) = 0,返回 365𝔽
  4. 如果 (ry 4) = 0,返回 366𝔽
  5. 返回 365𝔽

21.4.1.6 DayFromYear ( y )

抽象操作 DayFromYear 接受参数 y(一个整数 Number)并返回一个整数 Number。它返回年份 y 第一天的天数。它在被调用时执行以下步骤:

  1. ry(y)。
  2. 注意:在以下步骤中, numYears1numYears4numYears100numYears400 分别表示在纪元和年份 y 开始之间发生的可被 1、4、100 和 400 整除的年数。如果 y纪元之前,该数字为负数。
  3. numYears1 为 (ry - 1970)。
  4. numYears4floor((ry - 1969) / 4)。
  5. numYears100floor((ry - 1901) / 100)。
  6. numYears400floor((ry - 1601) / 400)。
  7. 返回 𝔽(365 × numYears1 + numYears4 - numYears100 + numYears400)。

21.4.1.7 TimeFromYear ( y )

抽象操作 TimeFromYear 接受参数 y(一个整数 Number)并返回一个时间值。它返回年份 y 开始的时间值。它在被调用时执行以下步骤:

  1. 返回 msPerDay × DayFromYear(y)。

21.4.1.8 YearFromTime ( t )

抽象操作 YearFromTime 接受参数 t(一个有限时间值)并返回一个整数 Number。它返回 t 所在的年份。它在被调用时执行以下步骤:

  1. 返回最大的整数 Number y(最接近 +∞),使得 TimeFromYear(y) ≤ t

21.4.1.9 DayWithinYear ( t )

抽象操作 DayWithinYear 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽365𝔽闭区间内的整数 Number。它在被调用时执行以下步骤:

  1. 返回 Day(t) - DayFromYear(YearFromTime(t))。

21.4.1.10 InLeapYear ( t )

抽象操作 InLeapYear 接受参数 t(一个有限时间值)并返回 +0𝔽1𝔽。如果 t 在闰年内,它返回 1𝔽,否则返回 +0𝔽。它在被调用时执行以下步骤:

  1. 如果 DaysInYear(YearFromTime(t)) 是 366𝔽,返回 1𝔽;否则返回 +0𝔽

21.4.1.11 MonthFromTime ( t )

抽象操作 MonthFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽11𝔽闭区间内的整数 Number。它返回一个标识 t 所在月份的 Number。月份值 +0𝔽 指定一月;1𝔽 指定二月;2𝔽 指定三月; 3𝔽 指定四月;4𝔽 指定五月;5𝔽 指定六月; 6𝔽 指定七月;7𝔽 指定八月;8𝔽 指定九月; 9𝔽 指定十月;10𝔽 指定十一月;11𝔽 指定十二月。注意 MonthFromTime(+0𝔽) = +0𝔽,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  3. 如果 dayWithinYear < 31𝔽,返回 +0𝔽
  4. 如果 dayWithinYear < 59𝔽 + inLeapYear,返回 1𝔽
  5. 如果 dayWithinYear < 90𝔽 + inLeapYear,返回 2𝔽
  6. 如果 dayWithinYear < 120𝔽 + inLeapYear,返回 3𝔽
  7. 如果 dayWithinYear < 151𝔽 + inLeapYear,返回 4𝔽
  8. 如果 dayWithinYear < 181𝔽 + inLeapYear,返回 5𝔽
  9. 如果 dayWithinYear < 212𝔽 + inLeapYear,返回 6𝔽
  10. 如果 dayWithinYear < 243𝔽 + inLeapYear,返回 7𝔽
  11. 如果 dayWithinYear < 273𝔽 + inLeapYear,返回 8𝔽
  12. 如果 dayWithinYear < 304𝔽 + inLeapYear,返回 9𝔽
  13. 如果 dayWithinYear < 334𝔽 + inLeapYear,返回 10𝔽
  14. 断言dayWithinYear < 365𝔽 + inLeapYear
  15. 返回 11𝔽

21.4.1.12 DateFromTime ( t )

抽象操作 DateFromTime 接受参数 t(一个有限时间值)并返回一个在从 1𝔽31𝔽闭区间内的整数 Number。它返回 t 所在月份的日期。它在被调用时执行以下步骤:

  1. inLeapYearInLeapYear(t)。
  2. dayWithinYearDayWithinYear(t)。
  3. monthMonthFromTime(t)。
  4. 如果 month+0𝔽,返回 dayWithinYear + 1𝔽
  5. 如果 month1𝔽,返回 dayWithinYear - 30𝔽
  6. 如果 month2𝔽,返回 dayWithinYear - 58𝔽 - inLeapYear
  7. 如果 month3𝔽,返回 dayWithinYear - 89𝔽 - inLeapYear
  8. 如果 month4𝔽,返回 dayWithinYear - 119𝔽 - inLeapYear
  9. 如果 month5𝔽,返回 dayWithinYear - 150𝔽 - inLeapYear
  10. 如果 month6𝔽,返回 dayWithinYear - 180𝔽 - inLeapYear
  11. 如果 month7𝔽,返回 dayWithinYear - 211𝔽 - inLeapYear
  12. 如果 month8𝔽,返回 dayWithinYear - 242𝔽 - inLeapYear
  13. 如果 month9𝔽,返回 dayWithinYear - 272𝔽 - inLeapYear
  14. 如果 month10𝔽,返回 dayWithinYear - 303𝔽 - inLeapYear
  15. 断言month11𝔽
  16. 返回 dayWithinYear - 333𝔽 - inLeapYear

21.4.1.13 WeekDay ( t )

抽象操作 WeekDay 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽6𝔽闭区间内的整数 Number。它返回一个标识 t 所在星期几的 Number。星期值 +0𝔽 指定星期日;1𝔽 指定星期一;2𝔽 指定星期二; 3𝔽 指定星期三;4𝔽 指定星期四;5𝔽 指定星期五; 6𝔽 指定星期六。注意 WeekDay(+0𝔽) = 4𝔽,对应于 1970 年 1 月 1 日星期四。它在被调用时执行以下步骤:

  1. 返回 𝔽((Day(t) + 4𝔽) 7)。

21.4.1.14 HourFromTime ( t )

抽象操作 HourFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽23𝔽闭区间内的整数 Number。它返回 t 所在天的小时。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerHour)) HoursPerDay)。

21.4.1.15 MinFromTime ( t )

抽象操作 MinFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽59𝔽闭区间内的整数 Number。它返回 t 所在小时的分钟。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerMinute)) MinutesPerHour)。

21.4.1.16 SecFromTime ( t )

抽象操作 SecFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽59𝔽闭区间内的整数 Number。它返回 t 所在分钟的秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽(floor((t / msPerSecond)) SecondsPerMinute)。

21.4.1.17 msFromTime ( t )

抽象操作 msFromTime 接受参数 t(一个有限时间值)并返回一个在从 +0𝔽999𝔽闭区间内的整数 Number。它返回 t 所在秒的毫秒数。它在被调用时执行以下步骤:

  1. 返回 𝔽((t) (msPerSecond))。

21.4.1.18 GetUTCEpochNanoseconds ( year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

抽象操作 GetUTCEpochNanoseconds 接受参数 year(一个整数)、 month(一个在 1 到 12 的闭区间内的整数)、day(一个在 1 到 31 的闭区间内的整数)、hour(一个在 0 到 23 的闭区间内的整数)、minute(一个在 0 到 59 的闭区间内的整数)、second(一个在 0 到 59 的闭区间内的整数)、millisecond(一个在 0 到 999 的闭区间内的整数)、microsecond(一个在 0 到 999 的闭区间内的整数)和 nanosecond(一个在 0 到 999 的闭区间内的整数)并返回一个 BigInt。返回值表示自纪元以来对应于给定 ISO 8601 日历日期和 UTC 挂钟时间的纳秒数。它在被调用时执行以下步骤:

  1. dateMakeDay(𝔽(year), 𝔽(month - 1), 𝔽(day))。
  2. timeMakeTime(𝔽(hour), 𝔽(minute), 𝔽(second), 𝔽(millisecond))。
  3. msMakeDate(date, time)。
  4. 断言ms 是一个整数 Number
  5. 返回 ((ms) × 106 + microsecond × 103 + nanosecond)。

21.4.1.19 时区标识符

ECMAScript 中的时区由时区标识符表示,它们是完全由在从 0x0000 到 0x007F 的闭区间内的代码单元组成的字符串。ECMAScript 实现支持的时区可能是可用命名时区,由 AvailableNamedTimeZoneIdentifiers 返回的时区标识符记录[[Identifier]] 字段表示,或者是偏移时区,由 IsTimeZoneOffsetString 返回 true 的字符串表示。

主要时区标识符是可用命名时区的首选标识符。 非主要时区标识符是不是主要时区标识符的可用命名时区标识符。 可用命名时区标识符要么是主要时区标识符,要么是非主要时区标识符。 每个可用命名时区标识符恰好与一个可用命名时区关联。 每个可用命名时区恰好与一个主要时区标识符和零个或多个非主要时区标识符关联。

ECMAScript 实现必须支持标识符为 "UTC" 的可用命名时区,该标识符必须是 UTC 时区的主要时区标识符。 此外,实现可以支持任意数量的其他可用命名时区。

遵循 ECMA-402 国际化 API 规范中描述的时区要求的实现称为时区感知的。 时区感知实现必须支持对应于 IANA 时区数据库的 Zone 和 Link 名称的可用命名时区,并且仅支持这些名称。 在时区感知实现中,主要时区标识符是 Zone 名称,非主要时区标识符是 Link 名称,分别在 IANA 时区数据库中,除非被 ECMA-402 规范中指定的 AvailableNamedTimeZoneIdentifiers 特别覆盖。 不支持整个 IANA 时区数据库的实现仍然建议使用 IANA 时区数据库名称作为标识符来表示时区。

21.4.1.20 GetNamedTimeZoneEpochNanoseconds ( timeZoneIdentifier, year, month, day, hour, minute, second, millisecond, microsecond, nanosecond )

实现定义的抽象操作 GetNamedTimeZoneEpochNanoseconds 接受参数 timeZoneIdentifier(一个字符串)、year(一个整数)、month(一个在 1 到 12 的闭区间内的整数)、day(一个在 1 到 31 的闭区间内的整数)、hour(一个在 0 到 23 的闭区间内的整数)、minute(一个在 0 到 59 的闭区间内的整数)、second(一个在 0 到 59 的闭区间内的整数)、millisecond(一个在 0 到 999 的闭区间内的整数)、microsecond(一个在 0 到 999 的闭区间内的整数)和 nanosecond(一个在 0 到 999 的闭区间内的整数)并返回一个 BigInt 的列表。 返回的列表中的每个值表示自纪元以来对应于给定 ISO 8601 日历日期和在由 timeZoneIdentifier 标识的命名时区中的挂钟时间的纳秒数。

当输入表示由于负时区转换(例如夏令时结束或由于时区规则变更导致时区偏移减少)而多次出现的本地时间时,返回的列表将有多个元素,并将按数值升序排序。 当输入表示由于正时区转换(例如夏令时开始或由于时区规则变更导致时区偏移增加)而跳过的本地时间时,返回的列表将为空。 否则,返回的列表将有一个元素。

GetNamedTimeZoneEpochNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:

  1. 断言timeZoneIdentifier"UTC"
  2. epochNanosecondsGetUTCEpochNanoseconds(year, month, day, hour, minute, second, millisecond, microsecond, nanosecond)。
  3. 返回 « epochNanoseconds »。
注意

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次,所以 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 11, 5, 1, 30, 0, 0, 0, 0) 将返回一个长度为 2 的列表,其中第一个元素表示 05:30 UTC(对应于 UTC 偏移 -04:00 的 01:30 美国东部夏令时),第二个元素表示 06:30 UTC(对应于 UTC 偏移 -05:00 的 01:30 美国东部标准时间)。

2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,所以 GetNamedTimeZoneEpochNanoseconds("America/New_York", 2017, 3, 12, 2, 30, 0, 0, 0, 0) 将返回一个空的列表

21.4.1.21 GetNamedTimeZoneOffsetNanoseconds ( timeZoneIdentifier, epochNanoseconds )

实现定义的抽象操作 GetNamedTimeZoneOffsetNanoseconds 接受参数 timeZoneIdentifier(一个字符串)和 epochNanoseconds(一个 BigInt)并返回一个整数

返回的整数表示由 timeZoneIdentifier 标识的命名时区在对应于相对于纪元epochNanoseconds 的瞬间的 UTC 偏移,均以纳秒为单位。

GetNamedTimeZoneOffsetNanoseconds 的默认实现,用于不包含任何时区本地政治规则的 ECMAScript 实现,在被调用时执行以下步骤:

  1. 断言timeZoneIdentifier"UTC"
  2. 返回 0。
注意

时区偏移值可能是正数或负数。

21.4.1.22 时区标识符记录

时区标识符记录是一个记录,用于描述一个可用命名时区标识符及其对应的主要时区标识符

时区标识符记录具有表 64 中列出的字段。

表 64:时区标识符记录字段
字段名 含义
[[Identifier]] 一个字符串 实现支持的可用命名时区标识符
[[PrimaryIdentifier]] 一个字符串 [[Identifier]] 解析到的主要时区标识符
注意

如果 [[Identifier]] 是一个主要时区标识符,那么 [[Identifier]] 就是 [[PrimaryIdentifier]]

21.4.1.23 AvailableNamedTimeZoneIdentifiers ( )

实现定义的抽象操作 AvailableNamedTimeZoneIdentifiers 不接受参数并返回一个时区标识符记录列表。 其结果描述此实现中所有可用命名时区标识符,以及对应于每个可用命名时区标识符主要时区标识符。 该列表根据每个时区标识符记录[[Identifier]] 字段排序。

时区感知实现,包括所有实现 ECMA-402 国际化 API 的实现,必须按照 ECMA-402 规范中指定的方式实现 AvailableNamedTimeZoneIdentifiers 抽象操作。 对于不是时区感知的实现,AvailableNamedTimeZoneIdentifiers 在被调用时执行以下步骤:

  1. 如果实现不包含任何时区的本地政治规则,那么
    1. 返回 « 时区标识符记录 { [[Identifier]]: "UTC", [[PrimaryIdentifier]]: "UTC" } »。
  2. identifiers 为按字典序代码单元顺序排序的唯一可用命名时区标识符列表
  3. result 为一个新的空列表
  4. 对于 identifiers 的每个元素 identifier,执行
    1. primaryidentifier
    2. 如果 identifier 是此实现中的非主要时区标识符并且 identifier 不是 "UTC",那么
      1. primary 为与 identifier 关联的主要时区标识符
      2. 注意:实现可能需要迭代解析 identifier 以获得主要时区标识符
    3. record时区标识符记录 { [[Identifier]]: identifier, [[PrimaryIdentifier]]: primary }。
    4. record 附加到 result
  5. 断言result 包含一个时区标识符记录 r,使得 r.[[Identifier]]"UTC" 并且 r.[[PrimaryIdentifier]]"UTC"
  6. 返回 result

21.4.1.24 SystemTimeZoneIdentifier ( )

实现定义的抽象操作 SystemTimeZoneIdentifier 不接受参数并返回一个字符串。 它返回一个表示宿主环境当前时区的字符串,该字符串要么是一个表示 UTC 偏移的字符串(IsTimeZoneOffsetString 对其返回 true),要么是一个主要时区标识符。 它在被调用时执行以下步骤:

  1. 如果实现仅支持 UTC 时区,返回 "UTC"
  2. systemTimeZoneString 为表示宿主环境当前时区的字符串,要么是一个主要时区标识符,要么是一个偏移时区标识符。
  3. 返回 systemTimeZoneString
注意

为了确保实现在 Date 对象的方法中通常提供的功能级别,建议 SystemTimeZoneIdentifier 返回对应于宿主环境时区设置的 IANA 时区名称(如果存在的话)。 GetNamedTimeZoneEpochNanosecondsGetNamedTimeZoneOffsetNanoseconds 必须反映该时区中标准时间和夏令时的本地政治规则(如果存在这些规则)。

例如,如果宿主环境是系统上的浏览器,用户选择了美国东部时间作为他们的时区, SystemTimeZoneIdentifier 返回 "America/New_York"

21.4.1.25 LocalTime ( t )

抽象操作 LocalTime 接受参数 t(一个有限时间值)并返回一个整数 Number。 它将 t 从 UTC 转换为本地时间。 应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。 它在被调用时执行以下步骤:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,那么
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((t) × 106))。
  4. offsetMstruncate(offsetNs / 106)。
  5. 返回 t + 𝔽(offsetMs)。
注意 1

如果实现中没有本地时间 t 的政治规则,结果就是 t,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

注意 2

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

注意 3

在负时区转换时,当有重复时间时(例如夏令时结束或时区调整减少),两个不同的输入时间值 tUTC 会转换为相同的本地时间 tlocal

LocalTime(UTC(tlocal)) 不一定总是等于 tlocal。相应地,UTC(LocalTime(tUTC)) 不一定总是等于 tUTC

21.4.1.26 UTC ( t )

抽象操作 UTC 接受参数 t(一个 Number)并返回一个时间值。 它将 t 从本地时间转换为 UTC 时间值。 应该使用在 t 时刻生效的标准时间和夏令时的本地政治规则来按照本节规定的方式确定结果。 它在被调用时执行以下步骤:

  1. 如果 t 不是有限的,返回 NaN
  2. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  3. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 是 true,那么
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  4. 否则,
    1. possibleInstantsGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(t)), (MonthFromTime(t)) + 1, (DateFromTime(t)), (HourFromTime(t)), (MinFromTime(t)), (SecFromTime(t)), (msFromTime(t)), 0, 0)。
    2. 注意:以下步骤确保当 t 表示在负时区转换时多次重复的本地时间(例如夏令时结束或由于时区规则变更导致时区偏移减少)或在正时区转换时跳过的本地时间(例如夏令时开始或由于时区规则变更导致时区偏移增加)时,t 使用转换前的时区偏移进行解释。
    3. 如果 possibleInstants 不为空,那么
      1. disambiguatedInstantpossibleInstants[0]。
    4. 否则,
      1. 注意:t 表示在正时区转换时跳过的本地时间(例如由于夏令时开始或时区规则变更增加 UTC 偏移)。
      2. possibleInstantsBeforeGetNamedTimeZoneEpochNanoseconds(systemTimeZoneIdentifier, (YearFromTime(tBefore)), (MonthFromTime(tBefore)) + 1, (DateFromTime(tBefore)), (HourFromTime(tBefore)), (MinFromTime(tBefore)), (SecFromTime(tBefore)), (msFromTime(tBefore)), 0, 0),其中 tBefore 是小于 t 的最大整数 Number,使得 possibleInstantsBefore 不为空(即,tBefore 表示转换前的最后一个本地时间)。
      3. disambiguatedInstantpossibleInstantsBefore 的最后一个元素。
    5. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, disambiguatedInstant)。
  5. offsetMstruncate(offsetNs / 106)。
  6. 返回 t - 𝔽(offsetMs)。

输入 t 名义上是一个时间值,但可以是任何 Number 值。 算法不得将 t 限制在时间值范围内,以便可以支持对应于时间值范围边界的输入,而不管本地 UTC 偏移如何。 例如,最大时间值是 8.64 × 1015,对应于 "+275760-09-13T00:00:00Z"。 在本地时区偏移在该瞬间比 UTC 提前 1 小时的环境中,它由更大的输入 8.64 × 1015 + 3.6 × 106 表示,对应于 "+275760-09-13T01:00:00+01:00"

如果实现中没有本地时间 t 的政治规则,结果就是 t,因为 SystemTimeZoneIdentifier 返回 "UTC"GetNamedTimeZoneOffsetNanoseconds 返回 0。

注意 1

时区感知实现(建议所有其他实现也如此)需要使用 IANA 时区数据库 https://www.iana.org/time-zones/ 的时区信息。

2017 年 11 月 5 日在 America/New_York 的凌晨 1:30 重复了两次(回退),但必须解释为 1:30 AM UTC-04 而不是 1:30 AM UTC-05。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 10, 5), MakeTime(1, 30, 0, 0)))) 中,offsetMs 的值是 -4 × msPerHour

2017 年 3 月 12 日在 America/New_York 的凌晨 2:30 不存在,但必须解释为 2:30 AM UTC-05(相当于 3:30 AM UTC-04)。 在 UTC(TimeClip(MakeDate(MakeDay(2017, 2, 12), MakeTime(2, 30, 0, 0)))) 中,offsetMs 的值是 -5 × msPerHour

注意 2

UTC(LocalTime(tUTC)) 不一定总是等于 tUTC。相应地,LocalTime(UTC(tlocal)) 不一定总是等于 tlocal

21.4.1.27 MakeTime ( hour, min, sec, ms )

抽象操作 MakeTime 接受参数 hour(一个 Number)、min(一个 Number)、sec(一个 Number)和 ms(一个 Number)并返回一个 Number。它 计算毫秒数。它在被调用时执行以下步骤:

  1. 如果 hour 不是有限的,min 不是有限的, sec 不是有限的,或 ms 不是有限的,返回 NaN
  2. h𝔽(! ToIntegerOrInfinity(hour))。
  3. m𝔽(! ToIntegerOrInfinity(min))。
  4. s𝔽(! ToIntegerOrInfinity(sec))。
  5. milli𝔽(! ToIntegerOrInfinity(ms))。
  6. 返回 ((h × msPerHour + m × msPerMinute) + s × msPerSecond) + milli
注意

MakeTime 中的算术是浮点算术,它不满足结合律,所以操作必须按正确的顺序执行。

21.4.1.28 MakeDay ( year, month, date )

抽象操作 MakeDay 接受参数 year(一个 Number)、month (一个 Number)和 date(一个 Number)并返回一个 Number。它计算天数。它在被调用时执行以下步骤:

  1. 如果 year 不是有限的,month 不是有限的,或 date 不是有限的,返回 NaN
  2. y𝔽(! ToIntegerOrInfinity(year))。
  3. m𝔽(! ToIntegerOrInfinity(month))。
  4. dt𝔽(! ToIntegerOrInfinity(date))。
  5. ymy + 𝔽(floor((m) / 12))。
  6. 如果 ym 不是有限的,返回 NaN
  7. mn𝔽((m) modulo 12)。
  8. 找到一个有限时间值 t,使得 YearFromTime(t) 是 ymMonthFromTime(t) 是 mn,并且 DateFromTime(t) 是 1𝔽;但如果这不可能(因为某些 参数超出范围),返回 NaN
  9. 返回 Day(t) + dt - 1𝔽

21.4.1.29 MakeDate ( day, time )

抽象操作 MakeDate 接受参数 day(一个 Number)和 time (一个 Number)并返回一个 Number。它计算毫秒数。它在被调用时执行以下步骤:

  1. 如果 day 不是有限的或 time 不是有限的,返回 NaN
  2. tvday × msPerDay + time
  3. 如果 tv 不是有限的,返回 NaN
  4. 返回 tv

21.4.1.30 MakeFullYear ( year )

抽象操作 MakeFullYear 接受参数 year(一个 Number)并返回一个整数 NumberNaN。它返回与 year整数部分关联的完整年份,将闭区间 0 到 99 中的任何值解释为自 1900 年开始以来的年数。为了与推算格里高利历保持一致,"完整年份"定义为自第 0 年(公元前 1 年)开始以来完整年份的有符号计数。它在被调用时执行以下步骤:

  1. 如果 yearNaN,返回 NaN
  2. truncated 为 ! ToIntegerOrInfinity(year)。
  3. 如果 truncated闭区间 0 到 99 中,返回 1900𝔽 + 𝔽(truncated)。
  4. 返回 𝔽(truncated)。

21.4.1.31 TimeClip ( time )

抽象操作 TimeClip 接受参数 time(一个 Number)并返回一个 Number。它计算毫秒数。它在被调用时执行以下步骤:

  1. 如果 time 不是有限的,返回 NaN
  2. 如果 abs((time)) > 8.64 × 1015, 返回 NaN
  3. 返回 𝔽(! ToIntegerOrInfinity(time))。

21.4.1.32 日期时间字符串格式

ECMAScript 基于 ISO 8601 日历日期扩展格式的简化版本定义了日期时间的字符串交换格式。格式如下: YYYY-MM-DDTHH:mm:ss.sssZ

其中各元素如下:

YYYY 是推算格里高利历中的年份,作为从 0000 到 9999 的四位十进制数字,或作为由 "+""-" 后跟六位十进制数字的扩展年份
- "-"(连字符)在字符串中字面出现两次。
MM 是一年中的月份,作为从 01(一月)到 12(十二月)的两位十进制数字。
DD 是一个月中的日期,作为从 01 到 31 的两位十进制数字。
T "T" 在字符串中字面出现,表示时间元素的开始。
HH 是自午夜以来经过的完整小时数,作为从 00 到 24 的两位十进制数字。
: ":"(冒号)在字符串中字面出现两次。
mm 是自小时开始以来的完整分钟数,作为从 00 到 59 的两位十进制数字。
ss 是自分钟开始以来的完整秒数,作为从 00 到 59 的两位十进制数字。
. "."(点)在字符串中字面出现。
sss 是自秒开始以来的完整毫秒数,作为三位十进制数字。
Z 是 UTC 偏移表示,指定为 "Z"(对于无偏移的 UTC)或作为 "+""-" 后跟时间表达式 HH:mm时区偏移字符串格式的子集,分别用于指示本地时间早于或晚于 UTC)

此格式包括仅日期形式:

YYYY
YYYY-MM
YYYY-MM-DD
    

它还包括"日期时间"形式,由上述仅日期形式之一紧接一个以下时间形式(可附加可选的 UTC 偏移表示)组成:

THH:mm
THH:mm:ss
THH:mm:ss.sss
    

包含超出边界或不符合要求元素的字符串不是此格式的有效实例。

注意 1

由于每一天都以午夜开始和结束,00:0024:00 这两种表示法可用于区分可能与一个日期关联的两个午夜。这意味着以下两种表示法指的是完全相同的时间点:1995-02-04T24:001995-02-05T00:00。将后一种形式解释为"日历日的结束"与 ISO 8601 一致,尽管该规范将其保留用于描述时间间隔,并且不允许在单个时间点的表示中使用。

注意 2

不存在指定民用时区缩写(如 CET、EST 等)的国际标准,有时同一缩写甚至用于两个非常不同的时区。出于这个原因,ISO 8601 和此格式都指定时区偏移的数字表示。

21.4.1.32.1 扩展年份

涵盖从 1970 年 1 月 1 日向前或向后约 273,790 年的完整时间值范围(21.4.1.1)需要表示 0 之前或 9999 之后的年份。ISO 8601 允许扩展年份表示,但仅在信息交换伙伴相互同意的情况下。在简化的 ECMAScript 格式中,这种扩展年份表示应有 6 位数字,并且始终以 + 或 - 符号为前缀。年份 0 被认为是正数,必须以 + 符号为前缀。将年份 0 表示为 -000000 是无效的。匹配带有扩展年份的日期时间字符串格式的字符串,如果表示超出时间值范围的时间瞬间,将被 Date.parse 视为不可识别,并导致该函数返回 NaN,而不回退到实现特定的行为或启发式。

注意

带有扩展年份的日期时间值示例:

-271821-04-20T00:00:00Z 公元前 271822 年
-000001-01-01T00:00:00Z 公元前 2 年
+000000-01-01T00:00:00Z 公元前 1 年
+000001-01-01T00:00:00Z 公元 1 年
+001970-01-01T00:00:00Z 公元 1970 年
+002009-12-15T00:00:00Z 公元 2009 年
+275760-09-13T00:00:00Z 公元 275760 年

21.4.1.33 时区偏移字符串格式

ECMAScript 定义了一个来源于 ISO 8601 的 UTC 偏移字符串交换格式。 该格式由以下语法描述。

语法

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

21.4.1.33.1 IsTimeZoneOffsetString ( offsetString )

抽象操作 IsTimeZoneOffsetString 接受参数 offsetString(一个 String)并返回一个 Boolean。返回值指示 offsetString 是否符合 UTCOffset 给出的语法。它在被调用时执行以下步骤:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 如果 parseResult 是一个错误的列表,返回 false
  3. 返回 true

21.4.1.33.2 ParseTimeZoneOffsetString ( offsetString )

抽象操作 ParseTimeZoneOffsetString 接受参数 offsetString (一个 String)并返回一个整数。返回值是对应于字符串 offsetString 的 UTC 偏移,以纳秒为单位。它在被调用时执行以下步骤:

  1. parseResultParseText(offsetString, UTCOffset)。
  2. 断言parseResult 不是一个错误的列表
  3. 断言parseResult 包含一个 ASCIISign 解析节点
  4. parsedSignparseResult 中包含的 ASCIISign 解析节点匹配的源文本
  5. 如果 parsedSign 是单个代码点 U+002D(连字符减号),那么
    1. sign 为 -1。
  6. 否则,
    1. sign 为 1。
  7. 注意:下面 StringToNumber 的应用不会丢失精度,因为每个解析值都保证是一个足够短的十进制数字字符串。
  8. 断言parseResult 包含一个 Hour 解析节点
  9. parsedHoursparseResult 中包含的 Hour 解析节点匹配的源文本
  10. hours(StringToNumber(CodePointsToString(parsedHours)))。
  11. 如果 parseResult 不包含 MinuteSecond 解析节点,那么
    1. minutes 为 0。
  12. 否则,
    1. parsedMinutesparseResult 中包含的第一个 MinuteSecond 解析节点匹配的源文本
    2. minutes(StringToNumber(CodePointsToString(parsedMinutes)))。
  13. 如果 parseResult 不包含两个 MinuteSecond 解析节点,那么
    1. seconds 为 0。
  14. 否则,
    1. parsedSecondsparseResult 中包含的第二个 MinuteSecond 解析节点匹配的源文本
    2. seconds(StringToNumber(CodePointsToString(parsedSeconds)))。
  15. 如果 parseResult 不包含 TemporalDecimalFraction 解析节点,那么
    1. nanoseconds 为 0。
  16. 否则,
    1. parsedFractionparseResult 中包含的 TemporalDecimalFraction 解析节点匹配的源文本
    2. fractionCodePointsToString(parsedFraction) 和 "000000000"字符串连接
    3. nanosecondsStringfraction 从 1 到 10 的子字符串
    4. nanoseconds(StringToNumber(nanosecondsString))。
  17. 返回 sign × (((hours × 60 + minutes) × 60 + seconds) × 109 + nanoseconds)。

21.4.2 Date 构造函数

Date 构造函数

  • %Date%
  • "Date" 属性在 全局对象 上的初始值。
  • 作为 构造函数 调用时,创建并初始化一个新的 Date。
  • 作为函数而非 构造函数 调用时,返回一个表示当前时间(UTC)的字符串。
  • 是一个其行为根据参数数量和类型而不同的函数。
  • 可作为类定义中 extends 子句的值使用。打算继承指定 Date 行为的子类 构造函数 必须包含对 Date 构造函数super 调用,以使用 [[DateValue]] 内部槽创建并初始化子类实例。

21.4.2.1 Date ( ...values )

当调用此函数时,将执行以下步骤:

  1. 如果 NewTarget 为 undefined,则
    1. now 为标识当前时间的 时间值(UTC)。
    2. 返回 ToDateString(now)。
  2. numberOfArgsvalues 中元素的数量。
  3. 如果 numberOfArgs = 0,则
    1. dv 为标识当前时间的 时间值(UTC)。
  4. 否则如果 numberOfArgs = 1,则
    1. valuevalues[0]。
    2. 如果 value 是一个对象value 具有 [[DateValue]] 内部槽,则
      1. tvvalue.[[DateValue]]
    3. 否则,
      1. v 为 ? ToPrimitive(value)。
      2. 如果 v 是字符串,则
        1. 断言:下一步永远不会返回 非正常完成,因为 v 是字符串
        2. tv 为以与 parse 方法 (21.4.3.2) 完全相同的方式解析 v 作为日期的结果。
      3. 否则,
        1. tv 为 ? ToNumber(v)。
    4. dvTimeClip(tv)。
  5. 否则,
    1. 断言numberOfArgs ≥ 2。
    2. y 为 ? ToNumber(values[0])。
    3. m 为 ? ToNumber(values[1])。
    4. 如果 numberOfArgs > 2,令 dt 为 ? ToNumber(values[2]);否则令 dt1𝔽
    5. 如果 numberOfArgs > 3,令 h 为 ? ToNumber(values[3]);否则令 h+0𝔽
    6. 如果 numberOfArgs > 4,令 min 为 ? ToNumber(values[4]);否则令 min+0𝔽
    7. 如果 numberOfArgs > 5,令 s 为 ? ToNumber(values[5]);否则令 s+0𝔽
    8. 如果 numberOfArgs > 6,令 milli 为 ? ToNumber(values[6]);否则令 milli+0𝔽
    9. yrMakeFullYear(y)。
    10. finalDateMakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli))。
    11. dvTimeClip(UTC(finalDate))。
  6. O 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Date.prototype%", « [[DateValue]] »)。
  7. 设置 O.[[DateValue]]dv
  8. 返回 O

21.4.3 Date 构造函数的属性

Date 构造函数

  • 具有 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 具有值为 7𝔽"length" 属性。
  • 具有以下属性:

21.4.3.1 Date.now ( )

此函数返回表示调用时 UTC 日期和时间的 时间值

21.4.3.2 Date.parse ( string )

此函数对其参数应用 ToString 运算符。如果 ToString 产生 非正常完成,则会立即返回该 Completion Record。否则,此函数将结果字符串作为日期和时间进行解释;返回一个 Number,即与该日期和时间对应的 UTC 时间值。字符串可能会被解释为本地时间、UTC 时间或其他时区的时间,具体取决于字符串的内容。函数首先尝试按照日期时间字符串格式 (21.4.1.32),包括扩展年份,解析该字符串。如果字符串不符合该格式,函数可以退回到实现相关的启发式算法或实现相关的日期格式。无法识别或包含越界格式元素值的字符串会导致该函数返回 NaN

如果字符串符合 日期时间字符串格式,则缺失的格式元素将用替代值补齐。当 MMDD 元素缺失时,使用 "01"。当 HHmmss 元素缺失时,使用 "00"。当 sss 元素缺失时,使用 "000"。当缺少 UTC 偏移表示时,仅日期形式被解释为 UTC 时间,日期-时间形式被解释为本地时间。

如果 x 是 ECMAScript 某一实现中毫秒数为零的 Date,则在该实现中,以下所有表达式(如果所有相关属性都是初始值)应产生相同的数值:

x.valueOf()
Date.parse(x.toString())
Date.parse(x.toUTCString())
Date.parse(x.toISOString())

然而,下面的表达式

Date.parse(x.toLocaleString())

不要求产生与前三个表达式相同的数值,并且通常当传入的字符串不符合日期时间字符串格式 (21.4.1.32),且无法由 toStringtoUTCString 方法在该实现中产生时,该函数的返回值是 实现定义 的。

21.4.3.3 Date.prototype

Date.prototype 的初始值是 Date 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

21.4.3.4 Date.UTC ( year [ , month [ , date [ , hours [ , minutes [ , seconds [ , ms ] ] ] ] ] ] )

当调用此函数时,将执行以下步骤:

  1. y 为 ? ToNumber(year)。
  2. 如果 month 存在,令 m 为 ? ToNumber(month);否则,令 m+0𝔽
  3. 如果 date 存在,令 dt 为 ? ToNumber(date);否则,令 dt1𝔽
  4. 如果 hours 存在,令 h 为 ? ToNumber(hours);否则,令 h+0𝔽
  5. 如果 minutes 存在,令 min 为 ? ToNumber(minutes);否则,令 min+0𝔽
  6. 如果 seconds 存在,令 s 为 ? ToNumber(seconds);否则,令 s+0𝔽
  7. 如果 ms 存在,令 milli 为 ? ToNumber(ms);否则,令 milli+0𝔽
  8. yrMakeFullYear(y)。
  9. 返回 TimeClip(MakeDate(MakeDay(yr, m, dt), MakeTime(h, min, s, milli)))。

该函数的 "length" 属性值为 7𝔽

注意

此函数与 Date 构造函数 有两点不同:它返回一个 Number 形式的 时间值,而不是创建一个 Date,并且参数被解释为 UTC,而不是本地时间。

21.4.4 Date 原型对象的属性

Date 原型对象

  • %Date.prototype%
  • 它本身是一个 普通对象
  • 不是 Date 实例,也没有 [[DateValue]] 内部槽。
  • 具有 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确规定,下文定义的 Date 原型对象的方法不是泛型的,传递给它们的 this 值必须是一个已经初始化了 [[DateValue]] 内部槽,并且该槽为一个 时间值 的对象。

21.4.4.1 Date.prototype.constructor

Date.prototype.constructor 的初始值是 %Date%

21.4.4.2 Date.prototype.getDate ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 DateFromTime(LocalTime(t))。

21.4.4.3 Date.prototype.getDay ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 WeekDay(LocalTime(t))。

21.4.4.4 Date.prototype.getFullYear ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 YearFromTime(LocalTime(t))。

21.4.4.5 Date.prototype.getHours ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 HourFromTime(LocalTime(t))。

21.4.4.6 Date.prototype.getMilliseconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 msFromTime(LocalTime(t))。

21.4.4.7 Date.prototype.getMinutes ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MinFromTime(LocalTime(t))。

21.4.4.8 Date.prototype.getMonth ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MonthFromTime(LocalTime(t))。

21.4.4.9 Date.prototype.getSeconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 SecFromTime(LocalTime(t))。

21.4.4.10 Date.prototype.getTime ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.11 Date.prototype.getTimezoneOffset ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 (t - LocalTime(t)) / msPerMinute

21.4.4.12 Date.prototype.getUTCDate ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 DateFromTime(t)。

21.4.4.13 Date.prototype.getUTCDay ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 WeekDay(t)。

21.4.4.14 Date.prototype.getUTCFullYear ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 YearFromTime(t)。

21.4.4.15 Date.prototype.getUTCHours ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 HourFromTime(t)。

21.4.4.16 Date.prototype.getUTCMilliseconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 msFromTime(t)。

21.4.4.17 Date.prototype.getUTCMinutes ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MinFromTime(t)。

21.4.4.18 Date.prototype.getUTCMonth ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 MonthFromTime(t)。

21.4.4.19 Date.prototype.getUTCSeconds ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则返回 NaN
  5. 返回 SecFromTime(t)。

21.4.4.20 Date.prototype.setDate ( date )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,则返回 NaN
  6. 设置 tLocalTime(t)。
  7. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  8. uTimeClip(UTC(newDate))。
  9. 设置 dateObject.[[DateValue]]u
  10. 返回 u

21.4.4.21 Date.prototype.setFullYear ( year [ , month [ , date ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. y 为 ? ToNumber(year)。
  5. 如果 tNaN,则设置 t+0𝔽;否则,设置 tLocalTime(t)。
  6. 如果 month 未给出,令 mMonthFromTime(t);否则,令 m 为 ? ToNumber(month)。
  7. 如果 date 未给出,令 dtDateFromTime(t);否则,令 dt 为 ? ToNumber(date)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. uTimeClip(UTC(newDate))。
  10. 设置 dateObject.[[DateValue]]u
  11. 返回 u

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 month,本方法表现为 month 的值为 getMonth()。如果未给出 date,则表现为 date 的值为 getDate()

21.4.4.22 Date.prototype.setHours ( hour [ , min [ , sec [ , ms ] ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 给出,令 m 为 ? ToNumber(min)。
  6. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,则返回 NaN
  9. 设置 tLocalTime(t)。
  10. 如果 min 未给出,令 mMinFromTime(t)。
  11. 如果 sec 未给出,令 sSecFromTime(t)。
  12. 如果 ms 未给出,令 millimsFromTime(t)。
  13. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  14. uTimeClip(UTC(date))。
  15. 设置 dateObject.[[DateValue]]u
  16. 返回 u

该方法的 "length" 属性值为 4𝔽

注意

如果未给出 min,本方法表现为 min 的值为 getMinutes()。如果未给出 sec,则表现为 sec 的值为 getSeconds()。如果未给出 ms,则表现为 ms 的值为 getMilliseconds()

21.4.4.23 Date.prototype.setMilliseconds ( ms )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. t 设为 LocalTime(t)。
  7. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  8. uTimeClip(UTC(MakeDate(Day(t), time)))。
  9. 设置 dateObject.[[DateValue]]u
  10. 返回 u

21.4.4.24 Date.prototype.setMinutes ( min [ , sec [ , ms ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. 设置 tLocalTime(t)。
  9. 如果 sec 未给出,令 sSecFromTime(t)。
  10. 如果 ms 未给出,令 millimsFromTime(t)。
  11. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  12. uTimeClip(UTC(date))。
  13. 设置 dateObject.[[DateValue]]u
  14. 返回 u

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 sec,本方法表现为 sec 的值为 getSeconds()。如果未给出 ms,则表现为 ms 的值为 getMilliseconds()

21.4.4.25 Date.prototype.setMonth ( month [ , date ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 给出,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. 设置 tLocalTime(t)。
  8. 如果 date 未给出,令 dtDateFromTime(t)。
  9. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  10. uTimeClip(UTC(newDate))。
  11. 设置 dateObject.[[DateValue]]u
  12. 返回 u

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 date,本方法表现为 date 的值为 getDate()

21.4.4.26 Date.prototype.setSeconds ( sec [ , ms ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. 设置 tLocalTime(t)。
  8. 如果 ms 未给出,令 millimsFromTime(t)。
  9. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  10. uTimeClip(UTC(date))。
  11. 设置 dateObject.[[DateValue]]u
  12. 返回 u

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 ms,本方法表现为 ms 的值为 getMilliseconds()

21.4.4.27 Date.prototype.setTime ( time )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. t 为 ? ToNumber(time)。
  4. vTimeClip(t)。
  5. 设置 dateObject.[[DateValue]]v
  6. 返回 v

21.4.4.28 Date.prototype.setUTCDate ( date )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. dt 为 ? ToNumber(date)。
  5. 如果 tNaN,返回 NaN
  6. newDateMakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t))。
  7. vTimeClip(newDate)。
  8. 设置 dateObject.[[DateValue]]v
  9. 返回 v

21.4.4.29 Date.prototype.setUTCFullYear ( year [ , month [ , date ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. 如果 tNaN,则设置 t+0𝔽
  5. y 为 ? ToNumber(year)。
  6. 如果 month 未给出,令 mMonthFromTime(t); 否则,令 m 为 ? ToNumber(month)。
  7. 如果 date 未给出,令 dtDateFromTime(t); 否则,令 dt 为 ? ToNumber(date)。
  8. newDateMakeDate(MakeDay(y, m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 month,本方法表现为 month 的值为 getUTCMonth()。如果未给出 date,则表现为 date 的值为 getUTCDate()

21.4.4.30 Date.prototype.setUTCHours ( hour [ , min [ , sec [ , ms ] ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. h 为 ? ToNumber(hour)。
  5. 如果 min 给出,令 m 为 ? ToNumber(min)。
  6. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  7. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  8. 如果 tNaN,返回 NaN
  9. 如果 min 未给出,令 mMinFromTime(t)。
  10. 如果 sec 未给出,令 sSecFromTime(t)。
  11. 如果 ms 未给出,令 millimsFromTime(t)。
  12. dateMakeDate(Day(t), MakeTime(h, m, s, milli))。
  13. vTimeClip(date)。
  14. 设置 dateObject.[[DateValue]]v
  15. 返回 v

该方法的 "length" 属性值为 4𝔽

注意

如果未给出 min,本方法表现为 min 的值为 getUTCMinutes()。如果未给出 sec,则表现为 sec 的值为 getUTCSeconds()。如果未给出 ms,则表现为 ms 的值为 getUTCMilliseconds()

21.4.4.31 Date.prototype.setUTCMilliseconds ( ms )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. ms 设为 ? ToNumber(ms)。
  5. 如果 tNaN,返回 NaN
  6. timeMakeTime(HourFromTime(t), MinFromTime(t), SecFromTime(t), ms)。
  7. vTimeClip(MakeDate(Day(t), time))。
  8. 设置 dateObject.[[DateValue]]v
  9. 返回 v

21.4.4.32 Date.prototype.setUTCMinutes ( min [ , sec [ , ms ] ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(min)。
  5. 如果 sec 给出,令 s 为 ? ToNumber(sec)。
  6. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  7. 如果 tNaN,返回 NaN
  8. 如果 sec 未给出,令 sSecFromTime(t)。
  9. 如果 ms 未给出,令 millimsFromTime(t)。
  10. dateMakeDate(Day(t), MakeTime(HourFromTime(t), m, s, milli))。
  11. vTimeClip(date)。
  12. 设置 dateObject.[[DateValue]]v
  13. 返回 v

该方法的 "length" 属性值为 3𝔽

注意

如果未给出 sec,本方法表现为 sec 的值为 getUTCSeconds()。如果未给出 ms,则表现为 ms 的值为 getUTCMilliseconds()

21.4.4.33 Date.prototype.setUTCMonth ( month [ , date ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. m 为 ? ToNumber(month)。
  5. 如果 date 给出,令 dt 为 ? ToNumber(date)。
  6. 如果 tNaN,返回 NaN
  7. 如果 date 未给出,令 dtDateFromTime(t)。
  8. newDateMakeDate(MakeDay(YearFromTime(t), m, dt), TimeWithinDay(t))。
  9. vTimeClip(newDate)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 date,本方法表现为 date 的值为 getUTCDate()

21.4.4.34 Date.prototype.setUTCSeconds ( sec [ , ms ] )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tdateObject.[[DateValue]]
  4. s 为 ? ToNumber(sec)。
  5. 如果 ms 给出,令 milli 为 ? ToNumber(ms)。
  6. 如果 tNaN,返回 NaN
  7. 如果 ms 未给出,令 millimsFromTime(t)。
  8. dateMakeDate(Day(t), MakeTime(HourFromTime(t), MinFromTime(t), s, milli))。
  9. vTimeClip(date)。
  10. 设置 dateObject.[[DateValue]]v
  11. 返回 v

该方法的 "length" 属性值为 2𝔽

注意

如果未给出 ms,本方法表现为 ms 的值为 getUTCMilliseconds()

21.4.4.35 Date.prototype.toDateString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 DateString(t)。

21.4.4.36 Date.prototype.toISOString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,抛出 RangeError 异常。
  5. 断言tv 是一个 整数 Number
  6. 如果 tv 所对应的年份不能用 日期时间字符串格式 表示,则抛出 RangeError 异常。
  7. 返回 tv 在 UTC 时标下、日期时间字符串格式 的字符串表示,包括所有格式元素及 UTC 偏移 "Z"。

21.4.4.37 Date.prototype.toJSON ( key )

此方法为 JSON.stringify (25.5.2) 提供 Date 的字符串表示。

调用该方法时,执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. tv 为 ? ToPrimitive(O, number)。
  3. 如果 tv 是 Numbertv 不是 有限值,则返回 null
  4. 返回 ? Invoke(O, "toISOString")。
注意 1

参数会被忽略。

注意 2

此方法有意设计为泛型;它不要求其 this 值为 Date。因此,可以转移到其他类型的对象上作为方法使用。但该对象必须有 toISOString 方法。

21.4.4.38 Date.prototype.toLocaleDateString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下 Date 的“日期”部分,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.39 Date.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下的 Date,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.40 Date.prototype.toLocaleTimeString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个字符串值。字符串内容是实现定义的,但旨在以方便且易于理解的形式,表示当前时区下 Date 的“时间”部分,符合宿主环境当前区域设置的习惯。

本方法的可选参数含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

21.4.4.41 Date.prototype.toString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 返回 ToDateString(tv)。
注意 1

对于任何 Date d,如果 d.[[DateValue]] 能被 1000 整除,则 Date.parse(d.toString()) 的结果等于 d.valueOf()。参见21.4.3.2

注意 2

此方法不是泛型;如果其 this 值不是 Date,则会抛出 TypeError 异常。因此,不能转移到其他类型的对象用作方法。

21.4.4.41.1 TimeString ( tv )

抽象操作 TimeString 接受参数 tv(Number,但不是 NaN),返回一个字符串。调用时执行以下步骤:

  1. hourToZeroPaddedDecimalString((HourFromTime(tv)), 2)。
  2. minuteToZeroPaddedDecimalString((MinFromTime(tv)), 2)。
  3. secondToZeroPaddedDecimalString((SecFromTime(tv)), 2)。
  4. 返回 字符串拼接 hour":"minute":"second、0x0020(空格)、"GMT"

21.4.4.41.2 DateString ( tv )

抽象操作 DateString 接受参数 tv(Number,但不是 NaN),返回一个字符串。调用时执行以下步骤:

  1. weekday表 65 中编号为 WeekDay(tv) 的 Name。
  2. month表 66 中编号为 MonthFromTime(tv) 的 Name。
  3. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  4. yvYearFromTime(tv)。
  5. 如果 yv+0𝔽yv > +0𝔽,则 yearSign 为空字符串;否则 yearSign"-"
  6. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  7. 返回 字符串拼接 weekday、0x0020(空格)、month、0x0020、day、0x0020、yearSignpaddedYear
表 65:一周中各天的名称
编号 名称
+0𝔽 "Sun"
1𝔽 "Mon"
2𝔽 "Tue"
3𝔽 "Wed"
4𝔽 "Thu"
5𝔽 "Fri"
6𝔽 "Sat"
表 66:一年中各月的名称
编号 名称
+0𝔽 "Jan"
1𝔽 "Feb"
2𝔽 "Mar"
3𝔽 "Apr"
4𝔽 "May"
5𝔽 "Jun"
6𝔽 "Jul"
7𝔽 "Aug"
8𝔽 "Sep"
9𝔽 "Oct"
10𝔽 "Nov"
11𝔽 "Dec"

21.4.4.41.3 TimeZoneString ( tv )

抽象操作 TimeZoneString 接受参数 tv整数 Number),返回一个字符串。调用时执行以下步骤:

  1. systemTimeZoneIdentifierSystemTimeZoneIdentifier()。
  2. 如果 IsTimeZoneOffsetString(systemTimeZoneIdentifier) 为 true,则
    1. offsetNsParseTimeZoneOffsetString(systemTimeZoneIdentifier)。
  3. 否则,
    1. offsetNsGetNamedTimeZoneOffsetNanoseconds(systemTimeZoneIdentifier, ((tv) × 106))。
  4. offset𝔽(truncate(offsetNs / 106))。
  5. 如果 offset+0𝔽offset > +0𝔽,则
    1. offsetSign"+"
    2. absOffsetoffset
  6. 否则,
    1. offsetSign"-"
    2. absOffset 为 -offset
  7. offsetMinToZeroPaddedDecimalString((MinFromTime(absOffset)), 2)。
  8. offsetHourToZeroPaddedDecimalString((HourFromTime(absOffset)), 2)。
  9. tzName 为一个实现定义的字符串,其值可以为空字符串,也可以是 0x0020(空格)、0x0028(左括号)、实现定义的时区名称和 0x0029(右括号)的字符串拼接。
  10. 返回 字符串拼接 offsetSignoffsetHouroffsetMintzName

21.4.4.41.4 ToDateString ( tv )

抽象操作 ToDateString 接受参数 tv整数 NumberNaN),返回一个字符串。调用时执行以下步骤:

  1. 如果 tvNaN,返回 "Invalid Date"
  2. tLocalTime(tv)。
  3. 返回 字符串拼接 DateString(t)、0x0020(空格)、TimeString(t) 和 TimeZoneString(tv)。

21.4.4.42 Date.prototype.toTimeString ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. tLocalTime(tv)。
  6. 返回 字符串拼接 TimeString(t) 和 TimeZoneString(tv)。

21.4.4.43 Date.prototype.toUTCString ( )

该方法返回一个字符串值,表示与 this 值对应的时间点。字符串格式基于 RFC 7231 的 "HTTP-date",并推广以支持 ECMAScript Dates 支持的完整时间范围。

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. tvdateObject.[[DateValue]]
  4. 如果 tvNaN,返回 "Invalid Date"
  5. weekday表 65 中编号为 WeekDay(tv) 的 Name。
  6. month表 66 中编号为 MonthFromTime(tv) 的 Name。
  7. dayToZeroPaddedDecimalString((DateFromTime(tv)), 2)。
  8. yvYearFromTime(tv)。
  9. 如果 yv+0𝔽yv > +0𝔽,则 yearSign 为空字符串;否则 yearSign"-"
  10. paddedYearToZeroPaddedDecimalString(abs((yv)), 4)。
  11. 返回 字符串拼接 weekday","、0x0020(空格)、day、0x0020、month、0x0020、yearSignpaddedYear、0x0020 和 TimeString(tv)。

21.4.4.44 Date.prototype.valueOf ( )

调用该方法时,执行以下步骤:

  1. dateObjectthis 值。
  2. 执行 ? RequireInternalSlot(dateObject, [[DateValue]])。
  3. 返回 dateObject.[[DateValue]]

21.4.4.45 Date.prototype [ %Symbol.toPrimitive% ] ( hint )

此方法被 ECMAScript 语言运算符调用,用于将 Date 转换为原始值。hint 的允许值为 "default""number""string"。Date 是内置 ECMAScript 对象中唯一将 "default" 视为等价于 "string" 的对象。所有其他内置 ECMAScript 对象都将 "default" 视为等价于 "number"

调用该方法时,执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,则抛出 TypeError 异常。
  3. 如果 hint"string""default",则
    1. tryFirststring
  4. 否则如果 hint"number",则
    1. tryFirstnumber
  5. 否则,
    1. 抛出 TypeError 异常。
  6. 返回 ? OrdinaryToPrimitive(O, tryFirst)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

本方法的 "name" 属性值为 "[Symbol.toPrimitive]"

21.4.5 Date 实例的属性

Date 实例是普通对象,继承自Date 原型对象的属性。Date 实例还拥有一个 [[DateValue]] 内部槽。[[DateValue]] 内部槽即该 Date 实例所表示的时间值

22 文本处理

22.1 字符串对象

22.1.1 String 构造函数

String 构造函数

  • %String%
  • "String" 属性在 全局对象 上的初始值。
  • 作为 构造函数 调用时,创建并初始化一个新的 String 对象。
  • 作为函数调用而非 构造函数 时,执行类型转换。
  • 可作为类定义中 extends 子句的值使用。打算继承指定 String 行为的子类 构造函数 必须包含对 String 构造函数super 调用,以用 [[StringData]] 内部槽创建并初始化子类实例。

22.1.1.1 String ( value )

当调用该函数时,执行以下步骤:

  1. 如果 value 未给出,则
    1. s 为空字符串。
  2. 否则,
    1. 如果 NewTarget 为 undefinedvalue 是 Symbol,则返回 SymbolDescriptiveString(value)。
    2. s 为 ? ToString(value)。
  3. 如果 NewTarget 为 undefined,返回 s
  4. 返回 StringCreate(s, ? GetPrototypeFromConstructor(NewTarget, "%String.prototype%"))。

22.1.2 String 构造函数的属性

String 构造函数

22.1.2.1 String.fromCharCode ( ...codeUnits )

该函数可以接收任意数量的参数,这些参数形成余参数 codeUnits

调用该函数时,执行以下步骤:

  1. result 为空字符串。
  2. 对于 codeUnits 中的每个元素 next,执行
    1. nextCU 为数值为 (? ToUint16(next)) 的码元。
    2. result 设为 字符串拼接 resultnextCU 的结果。
  3. 返回 result

该函数的 "length" 属性值为 1𝔽

22.1.2.2 String.fromCodePoint ( ...codePoints )

该函数可以接收任意数量的参数,这些参数形成余参数 codePoints

调用该函数时,执行以下步骤:

  1. result 为空字符串。
  2. 对于 codePoints 中的每个元素 next,执行
    1. nextCP 为 ? ToNumber(next)。
    2. 如果 nextCP 不是 整数 Number,抛出 RangeError 异常。
    3. 如果 (nextCP) < 0 或 (nextCP) > 0x10FFFF,抛出 RangeError 异常。
    4. result 设为 字符串拼接 resultUTF16EncodeCodePoint((nextCP)) 的结果。
  3. 断言:如果 codePoints 为空,则 result 为空字符串。
  4. 返回 result

该函数的 "length" 属性值为 1𝔽

22.1.2.3 String.prototype

String.prototype 的初始值为 String 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.2.4 String.raw ( template, ...substitutions )

该函数可以接收可变数量的参数。第一个参数为 template,其余参数组成 List substitutions

调用该函数时,执行以下步骤:

  1. substitutionCountsubstitutions 的元素个数。
  2. cooked 为 ? ToObject(template)。
  3. literals 为 ? ToObject(? Get(cooked, "raw"))。
  4. literalCount 为 ? LengthOfArrayLike(literals)。
  5. 如果 literalCount ≤ 0,返回空字符串。
  6. R 为空字符串。
  7. nextIndex 为 0。
  8. 重复,
    1. nextLiteralVal 为 ? Get(literals, ! ToString(𝔽(nextIndex)))。
    2. nextLiteral 为 ? ToString(nextLiteralVal)。
    3. R 设为 字符串拼接 RnextLiteral 的结果。
    4. 如果 nextIndex + 1 = literalCount,返回 R
    5. 如果 nextIndex < substitutionCount,则
      1. nextSubValsubstitutions[nextIndex]。
      2. nextSub 为 ? ToString(nextSubVal)。
      3. R 设为 字符串拼接 RnextSub 的结果。
    6. nextIndex 设为 nextIndex + 1。
注意

该函数用于作为标记模板(Tagged Template)(13.3.11)的标记函数使用。当以此方式调用时,第一个参数将是格式良好的模板对象,其余参数是替换值。

22.1.3 String 原型对象的属性

String 原型对象

  • %String.prototype%
  • 是 String 特殊对象,并拥有为此类对象规定的内部方法。
  • 有一个 [[StringData]] 内部槽,其值为空字符串。
  • 有一个 "length" 属性,其初始值为 +0𝔽,属性为 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。
  • 有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%

除非另有明确声明,下文定义的 String 原型对象的方法都不是泛型方法,传递给它们的 this 值必须是 String 值或具有已初始化为 String 值的 [[StringData]] 内部槽的对象。

22.1.3.1 String.prototype.at ( index )

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klen + relativeIndex
  7. 如果 k < 0 或 klen,返回 undefined
  8. 返回 substring Skk + 1。

22.1.3.2 String.prototype.charAt ( pos )

注 1

此方法返回包含在将此对象转换为 String 后的字符串中索引为 pos 的码元的单元素字符串。如果该索引处没有元素,则返回空字符串。结果是 String值,而不是 String 对象。

如果 pos整数 Number,则 x.charAt(pos) 的结果等价于 x.substring(pos, pos + 1)

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回空字符串。
  6. 返回 substring Spositionposition + 1。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.3 String.prototype.charCodeAt ( pos )

注 1

此方法返回一个 Number(一个非负的整数 Number,小于 216),表示将此对象转换为 String 后字符串中索引为 pos 处的码元的数值。如果该索引处没有元素,则结果为 NaN

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回 NaN
  6. 返回 Number value for 字符串 S 中索引为 position 的码元的数值。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.4 String.prototype.codePointAt ( pos )

注 1

此方法返回一个非负的整数 Number,小于等于 0x10FFFF𝔽,表示在将该对象转换为 String 后字符串中索引为 pos 处开始的 UTF-16 编码码点(6.1.4)的数值。如果该索引处没有元素,则结果为 undefined。如果 pos 处不是有效的 UTF-16 代理对 的开始,则结果为 pos 处的码元。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. position 为 ? ToIntegerOrInfinity(pos)。
  4. sizeS 的长度。
  5. 如果 position < 0 或 positionsize,返回 undefined
  6. cpCodePointAt(S, position)。
  7. 返回 𝔽(cp.[[CodePoint]])。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.5 String.prototype.concat ( ...args )

注 1

调用此方法时,返回由 this 值(转换为 String)码元后跟每个参数转换为 String 后的码元组成的 String 值。结果是 String值,而不是 String 对象。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. RS
  4. 对于 args 中的每个元素 next,执行
    1. nextString 为 ? ToString(next)。
    2. R 设为 字符串拼接 RnextString 的结果。
  5. 返回 R

该方法的 "length" 属性值为 1𝔽

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.6 String.prototype.constructor

String.prototype.constructor 的初始值为 %String%

22.1.3.7 String.prototype.endsWith ( searchString [ , endPosition ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. lenS 的长度。
  7. 如果 endPositionundefined,令 poslen;否则令 pos 为 ? ToIntegerOrInfinity(endPosition)。
  8. endclamping pos 介于 0 和 len 之间的结果。
  9. searchLengthsearchStr 的长度。
  10. 如果 searchLength = 0,返回 true
  11. startend - searchLength
  12. 如果 start < 0,返回 false
  13. substringsubstring Sstartend
  14. 如果 substring 等于 searchStr,返回 true
  15. 返回 false
注 1

如果 searchString(转换为 String)码元序列与本对象(转换为 String)中从 endPosition - length(this) 开始的对应码元相同,则该方法返回 true,否则返回 false

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.8 String.prototype.includes ( searchString [ , position ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. pos 为 ? ToIntegerOrInfinity(position)。
  7. 断言:如果 positionundefined,则 pos 为 0。
  8. lenS 的长度。
  9. startclamping pos 介于 0 和 len 之间的结果。
  10. indexStringIndexOf(S, searchStr, start)。
  11. 如果 indexnot-found,返回 false
  12. 返回 true
注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引大于等于 position,则该函数返回 true;否则返回 false。如果 positionundefined,则默认值为 0,因此会搜索整个字符串。

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.9 String.prototype.indexOf ( searchString [ , position ] )

注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引大于等于 position,则返回最小的此类索引,否则返回 -1𝔽。如果 positionundefined,则假定为 +0𝔽,即搜索整个字符串。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. searchStr 为 ? ToString(searchString)。
  4. pos 为 ? ToIntegerOrInfinity(position)。
  5. 断言:如果 positionundefined,则 pos 为 0。
  6. lenS 的长度。
  7. startclamping pos 介于 0 和 len 之间的结果。
  8. resultStringIndexOf(S, searchStr, start)。
  9. 如果 resultnot-found,返回 -1𝔽
  10. 返回 𝔽(result)。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.10 String.prototype.isWellFormed ( )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. 返回 IsStringWellFormedUnicode(S)。

22.1.3.11 String.prototype.lastIndexOf ( searchString [ , position ] )

注 1

如果 searchString 作为子串出现在将此对象转换为 String 后的结果中,且索引小于等于 position,则返回最大的此类索引,否则返回 -1𝔽。如果 positionundefined,则假定为字符串长度,即搜索整个字符串。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. searchStr 为 ? ToString(searchString)。
  4. numPos 为 ? ToNumber(position)。
  5. 断言:如果 positionundefined,则 numPosNaN
  6. 如果 numPosNaN,令 pos 为 +∞;否则,令 pos 为 ! ToIntegerOrInfinity(numPos)。
  7. lenS 的长度。
  8. searchLensearchStr 的长度。
  9. startclamping pos 介于 0 和 len - searchLen 之间的结果。
  10. resultStringLastIndexOf(S, searchStr, start)。
  11. 如果 resultnot-found,返回 -1𝔽
  12. 返回 𝔽(result)。
注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.12 String.prototype.localeCompare ( that [ , reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法返回一个除 NaN 以外的 Number,表示将 this 值(转换为字符串 S)与 that(转换为字符串 thatValue)进行实现定义的本地敏感字符串比较的结果。该结果旨在与 宿主环境当前区域设置的排序顺序相对应,当 S 排在 thatValue 之前时为负,排在之后时为正,否则为零(表示 SthatValue 之间无相对顺序)。

在执行比较前,该方法会按如下步骤准备字符串:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. thatValue 为 ? ToString(that)。

本方法的第二和第三个可选参数的含义在 ECMA-402 规范中定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

实际返回值为实现定义,以允许编码额外信息,但作为两个参数的方法时,要求作为一致的比较器,对所有字符串集合定义全序关系。该方法还要求根据 Unicode 标准识别和遵循规范等价,包括在比较可区分但规范等价的字符串时返回 +0𝔽

注 1

此方法本身不适合作为 Array.prototype.sort 的参数,因为后者需要两个参数的函数。

注 2

此方法可依赖 ECMAScript 环境从宿主环境获得的任意语言/区域敏感比较功能,并旨在按照宿主环境当前区域设置的习惯进行比较。但无论比较能力如何,本方法都必须根据 Unicode 标准识别和遵循规范等价——例如,以下比较都必须返回 +0𝔽

// Å ANGSTROM SIGN vs.
// Å LATIN CAPITAL LETTER A + COMBINING RING ABOVE
"\u212B".localeCompare("A\u030A")

// Ω OHM SIGN vs.
// Ω GREEK CAPITAL LETTER OMEGA
"\u2126".localeCompare("\u03A9")

// ṩ LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE vs.
// ṩ LATIN SMALL LETTER S + COMBINING DOT ABOVE + COMBINING DOT BELOW
"\u1E69".localeCompare("s\u0307\u0323")

// ḍ̇ LATIN SMALL LETTER D WITH DOT ABOVE + COMBINING DOT BELOW vs.
// ḍ̇ LATIN SMALL LETTER D WITH DOT BELOW + COMBINING DOT ABOVE
"\u1E0B\u0323".localeCompare("\u1E0D\u0307")

// 가 HANGUL CHOSEONG KIYEOK + HANGUL JUNGSEONG A vs.
// 가 HANGUL SYLLABLE GA
"\u1100\u1161".localeCompare("\uAC00")

关于规范等价的定义和讨论,参见 Unicode 标准第 2 章和第 3 章,以及 Unicode Standard Annex #15, Unicode Normalization FormsUnicode Technical Note #5, Canonical Equivalence in Applications。另见 Unicode Technical Standard #10, Unicode Collation Algorithm

建议本方法不应遵循 Unicode 兼容等价或 Unicode 标准第 3 章第 3.7 节定义的兼容分解。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.13 String.prototype.match ( regexp )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. matcher 为 ? GetMethod(regexp, %Symbol.match%)。
    2. 如果 matcher 不为 undefined,则
      1. 返回 ? Call(matcher, regexp, « O »)。
  3. S 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, undefined)。
  5. 返回 ? Invoke(rx, %Symbol.match%, « S »)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.14 String.prototype.matchAll ( regexp )

该方法对将 this 值表示的字符串与 regexp 进行正则表达式匹配,并返回一个迭代器,该迭代器会产生匹配结果。每个匹配结果是一个数组,其第一个元素为匹配到的字符串片段,后跟任何捕获组匹配到的片段。如果正则表达式从未匹配,返回的迭代器不会产生任何匹配结果。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. isRegExp 为 ? IsRegExp(regexp)。
    2. 如果 isRegExptrue,则
      1. flags 为 ? Get(regexp, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",抛出 TypeError 异常。
    3. matcher 为 ? GetMethod(regexp, %Symbol.matchAll%)。
    4. 如果 matcher 不为 undefined,则
      1. 返回 ? Call(matcher, regexp, « O »)。
  3. S 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, "g")。
  5. 返回 ? Invoke(rx, %Symbol.matchAll%, « S »)。
注 1
此方法有意设计为泛型,不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。
注 2
String.prototype.split 类似,String.prototype.matchAll 通常不应改变其输入。

22.1.3.15 String.prototype.normalize ( [ form ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. 如果 formundefined,令 f"NFC"
  4. 否则,令 f 为 ? ToString(form)。
  5. 如果 f 不是 "NFC""NFD""NFKC""NFKD" 之一,则抛出 RangeError 异常。
  6. ns 为将 S最新 Unicode 标准,Normalization Forms 中由 f 命名的规范形式规范化后的字符串值。
  7. 返回 ns

此方法有意设计为泛型,不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。

22.1.3.16 String.prototype.padEnd ( maxLength [ , fillString ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 返回 ? StringPaddingBuiltinsImpl(O, maxLength, fillString, end)。

22.1.3.17 String.prototype.padStart ( maxLength [ , fillString ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 返回 ? StringPaddingBuiltinsImpl(O, maxLength, fillString, start)。

22.1.3.17.1 StringPaddingBuiltinsImpl ( O, maxLength, fillString, placement )

抽象操作 StringPaddingBuiltinsImpl 接收参数 OECMAScript 语言值)、maxLengthECMAScript 语言值)、fillStringECMAScript 语言值)和 placementstartend),返回字符串或抛出异常。调用时执行以下步骤:

  1. S 为 ? ToString(O)。
  2. intMaxLength(? ToLength(maxLength))。
  3. stringLengthS 的长度。
  4. 如果 intMaxLengthstringLength,返回 S
  5. 如果 fillStringundefined,设置 fillString 为仅包含码元 0x0020(空格)的字符串。
  6. 否则,设置 fillString 为 ? ToString(fillString)。
  7. 返回 StringPad(S, intMaxLength, fillString, placement)。

22.1.3.17.2 StringPad ( S, maxLength, fillString, placement )

抽象操作 StringPad 接收参数 S(字符串)、maxLength(非负整数)、fillString(字符串)和 placementstartend),返回字符串。调用时执行以下步骤:

  1. stringLengthS 的长度。
  2. 如果 maxLengthstringLength,返回 S
  3. 如果 fillString 为空字符串,返回 S
  4. fillLenmaxLength - stringLength
  5. truncatedStringFiller 为重复拼接 fillString 并截断为 fillLen 长度的字符串。
  6. 如果 placementstart,返回 字符串拼接 truncatedStringFillerS 的结果。
  7. 否则,返回 字符串拼接 StruncatedStringFiller 的结果。
注 1

maxLength 参数会被限制,不能小于 S 的长度。

注 2

fillString 参数的默认值为 " "(仅包含码元 0x0020 空格的字符串)。

22.1.3.17.3 ToZeroPaddedDecimalString ( n, minLength )

抽象操作 ToZeroPaddedDecimalString 接收参数 n(非负整数)和 minLength(非负整数),返回字符串。调用时执行以下步骤:

  1. Sn 的字符串表示,格式为十进制数。
  2. 返回 StringPad(S, minLength, "0", start)。

22.1.3.18 String.prototype.repeat ( count )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. n 为 ? ToIntegerOrInfinity(count)。
  4. 如果 n < 0 或 n = +∞,抛出 RangeError 异常。
  5. 如果 n = 0,返回空字符串。
  6. 返回由 S 拼接 n 次组成的字符串值。
注 1

此方法会创建由 this 值(转换为字符串)的码元重复 count 次组成的字符串值。

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.19 String.prototype.replace ( searchValue, replaceValue )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 searchValue 既不是 undefined 也不是 null,则
    1. replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    2. 如果 replacer 不为 undefined,则
      1. 返回 ? Call(replacer, searchValue, « O, replaceValue »)。
  3. string 为 ? ToString(O)。
  4. searchString 为 ? ToString(searchValue)。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设为 ? ToString(replaceValue)。
  7. searchLengthsearchString 的长度。
  8. positionStringIndexOf(string, searchString, 0)。
  9. 如果 positionnot-found,返回 string
  10. precedingsubstring string 从 0 到 position
  11. followingsubstring stringposition + searchLength
  12. 如果 functionalReplacetrue,则
    1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(position), string »))。
  13. 否则,
    1. 断言replaceValue 是 String
    2. captures 为新的空List
    3. replacement 为 ! GetSubstitution(searchString, string, position, captures, undefined, replaceValue)。
  14. 返回 字符串拼接 precedingreplacementfollowing

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.19.1 GetSubstitution ( matched, str, position, captures, namedCaptures, replacementTemplate )

抽象操作 GetSubstitution 接收参数 matched(字符串)、str(字符串)、position(非负整数)、captures(字符串或 undefinedList)、namedCaptures(对象或 undefined)、replacementTemplate(字符串),返回字符串或抛出异常。此抽象操作中,十进制数字是 0x0030 (DIGIT ZERO) 到 0x0039 (DIGIT NINE) 区间的码元。调用时执行以下步骤:

  1. stringLengthstr 的长度。
  2. 断言positionstringLength
  3. result 为空字符串。
  4. templateRemainderreplacementTemplate
  5. 重复,直到 templateRemainder 为空字符串,
    1. 注:以下步骤隔离 reftemplateRemainder 的前缀),确定 refReplacement(其替换内容),然后将该替换内容追加到 result
    2. 如果 templateRemainder"$$" 开头,则
      1. ref"$$"
      2. refReplacement"$"
    3. 否则,如果 templateRemainder"$`" 开头,则
      1. ref"$`"
      2. refReplacementsubstring str 从 0 到 position
    4. 否则,如果 templateRemainder"$&" 开头,则
      1. ref"$&"
      2. refReplacementmatched
    5. 否则,如果 templateRemainder"$'"(0x0024(美元符号)后接 0x0027(撇号))开头,则
      1. ref"$'"
      2. matchLengthmatched 的长度。
      3. tailPosposition + matchLength
      4. refReplacementsubstring strmin(tailPos, stringLength)。
      5. 注:tailPos 只有在该抽象操作由对 %RegExp.prototype% 的 %Symbol.replace% 内置方法调用,且对象的 "exec" 属性不是内置 %RegExp.prototype.exec% 时才会超过 stringLength
    6. 否则,如果 templateRemainder"$" 后跟 1 个或多个十进制数字开头,则
      1. 如果 templateRemainder"$" 后跟 2 个或更多十进制数字开头,令 digitCount 为 2,否则为 1。
      2. digitssubstring templateRemainder 从 1 到 1 + digitCount
      3. index(StringToNumber(digits))。
      4. 断言:0 ≤ index ≤ 99。
      5. captureLencaptures 的元素个数。
      6. 如果 index > captureLendigitCount = 2,则
        1. 注:两位数替换模式指定的索引超出捕获组数量时,视为一位数替换模式后跟一个字面数字。
        2. digitCount 为 1。
        3. digitssubstring digits 从 0 到 1。
        4. index(StringToNumber(digits))。
      7. refsubstring templateRemainder 从 0 到 1 + digitCount
      8. 如果 1 ≤ indexcaptureLen,则
        1. capturecaptures[index - 1]。
        2. 如果 captureundefined,则
          1. refReplacement 为空字符串。
        3. 否则,
          1. refReplacementcapture
      9. 否则,
        1. refReplacementref
    7. 否则,如果 templateRemainder"$<" 开头,则
      1. gtPosStringIndexOf(templateRemainder, ">", 0)。
      2. 如果 gtPosnot-foundnamedCapturesundefined,则
        1. ref"$<"
        2. refReplacementref
      3. 否则,
        1. refsubstring templateRemainder 从 0 到 gtPos + 1。
        2. groupNamesubstring templateRemainder 从 2 到 gtPos
        3. 断言namedCaptures 是对象
        4. capture 为 ? Get(namedCaptures, groupName)。
        5. 如果 captureundefined,则
          1. refReplacement 为空字符串。
        6. 否则,
          1. refReplacement 为 ? ToString(capture)。
    8. 否则,
      1. refsubstring templateRemainder 从 0 到 1。
      2. refReplacementref
    9. refLengthref 的长度。
    10. templateRemainder 设为 substring templateRemainderrefLength
    11. result 设为 字符串拼接 resultrefReplacement 的结果。
  6. 返回 result

22.1.3.20 String.prototype.replaceAll ( searchValue, replaceValue )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 searchValue 既不是 undefined 也不是 null,则
    1. isRegExp 为 ? IsRegExp(searchValue)。
    2. 如果 isRegExptrue,则
      1. flags 为 ? Get(searchValue, "flags")。
      2. 执行 ? RequireObjectCoercible(flags)。
      3. 如果 ? ToString(flags) 不包含 "g",抛出 TypeError 异常。
    3. replacer 为 ? GetMethod(searchValue, %Symbol.replace%)。
    4. 如果 replacer 不为 undefined,则
      1. 返回 ? Call(replacer, searchValue, « O, replaceValue »)。
  3. string 为 ? ToString(O)。
  4. searchString 为 ? ToString(searchValue)。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. replaceValue 设为 ? ToString(replaceValue)。
  7. searchLengthsearchString 的长度。
  8. advanceBymax(1, searchLength)。
  9. matchPositions 为新的空 List
  10. positionStringIndexOf(string, searchString, 0)。
  11. 重复,直到 positionnot-found
    1. position 添加到 matchPositions
    2. position 设为 StringIndexOf(string, searchString, position + advanceBy)。
  12. endOfLastMatch 为 0。
  13. result 为空字符串。
  14. 对于 matchPositions 中的每个元素 p,执行
    1. preservedsubstring stringendOfLastMatchp
    2. 如果 functionalReplacetrue,则
      1. replacement 为 ? ToString(? Call(replaceValue, undefined, « searchString, 𝔽(p), string »))。
    3. 否则,
      1. 断言replaceValue 是 String
      2. captures 为新的空List
      3. replacement 为 ! GetSubstitution(searchString, string, p, captures, undefined, replaceValue)。
    4. result 设为 字符串拼接 resultpreservedreplacement 的结果。
    5. endOfLastMatch 设为 p + searchLength
  15. 如果 endOfLastMatch < string 的长度,则
    1. result 设为 字符串拼接 resultsubstring stringendOfLastMatch
  16. 返回 result

22.1.3.21 String.prototype.search ( regexp )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 regexp 既不是 undefined 也不是 null,则
    1. searcher 为 ? GetMethod(regexp, %Symbol.search%)。
    2. 如果 searcher 不为 undefined,则
      1. 返回 ? Call(searcher, regexp, « O »)。
  3. string 为 ? ToString(O)。
  4. rx 为 ? RegExpCreate(regexp, undefined)。
  5. 返回 ? Invoke(rx, %Symbol.search%, « string »)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.22 String.prototype.slice ( start, end )

该方法返回将此对象转换为字符串后的子串,从索引 start 开始,到但不包括索引 end(或若 endundefined,则直到字符串末尾)。如果 start 为负,则视为 sourceLength + start,其中 sourceLength 是字符串长度。如果 end 为负,则视为 sourceLength + end。结果是 String值,而不是 String 对象。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. intStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 intStart = -∞,令 from 为 0。
  6. 否则若 intStart < 0,令 frommax(len + intStart, 0)。
  7. 否则,令 frommin(intStart, len)。
  8. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 intEnd = -∞,令 to 为 0。
  10. 否则若 intEnd < 0,令 tomax(len + intEnd, 0)。
  11. 否则,令 tomin(intEnd, len)。
  12. 如果 fromto,返回空字符串。
  13. 返回 substring Sfromto

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此可以转移到其他类型的对象上作为方法使用。

22.1.3.23 String.prototype.split ( separator, limit )

该方法返回一个数组,将此对象转换为字符串后的子串存储在其中。子串是通过从左到右查找 separator 的出现位置确定的;这些出现位置不会包含在返回数组的任何字符串中,而是用来分割字符串。separator 的值可以是任意长度的字符串,也可以是具有 %Symbol.split% 方法的对象(如 RegExp)。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. 如果 separator 既不是 undefined 也不是 null,则
    1. splitter 为 ? GetMethod(separator, %Symbol.split%)。
    2. 如果 splitter 不为 undefined,则
      1. 返回 ? Call(splitter, separator, « O, limit »)。
  3. S 为 ? ToString(O)。
  4. 如果 limitundefined,令 lim 为 232 - 1;否则令 lim(? ToUint32(limit))。
  5. R 为 ? ToString(separator)。
  6. 如果 lim = 0,则
    1. 返回 CreateArrayFromList(« »)。
  7. 如果 separatorundefined,则
    1. 返回 CreateArrayFromListS »)。
  8. separatorLengthR 的长度。
  9. 如果 separatorLength = 0,则
    1. strLenS 的长度。
    2. outLenclamping lim 在 0 和 strLen 之间的结果。
    3. headsubstring S 从 0 到 outLen
    4. codeUnits 为一个 List,包含 head 的所有码元。
    5. 返回 CreateArrayFromList(codeUnits)。
  10. 如果 S 为空字符串,返回 CreateArrayFromListS »)。
  11. substrings 为新的空 List
  12. i 为 0。
  13. jStringIndexOf(S, R, 0)。
  14. 重复,直到 jnot-found
    1. Tsubstring Sij
    2. T 添加到 substrings
    3. 如果 substrings 的元素个数为 lim,返回 CreateArrayFromList(substrings)。
    4. i 设为 j + separatorLength
    5. j 设为 StringIndexOf(S, R, i)。
  15. Tsubstring Si
  16. T 添加到 substrings
  17. 返回 CreateArrayFromList(substrings)。
注 1

separator 的值可以为空字符串。在这种情况下,separator 不会匹配输入字符串开头或结尾的空子串,也不会匹配前一个分隔符匹配后结尾的空子串。如果 separator 为空字符串,则字符串被拆分为单个码元元素;结果数组的长度等于字符串的长度,每个子串只包含一个码元。

如果 this 值(或其转换结果)为空字符串,则结果取决于 separator 能否匹配空字符串。如果可以,结果数组不包含任何元素;否则,结果数组包含一个元素,即空字符串。

如果 separatorundefined,结果数组只包含一个字符串,即 this 的值(转换为字符串)。如果 limit 不为 undefined,则输出数组会被截断为不超过 limit 个元素。

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.24 String.prototype.startsWith ( searchString [ , position ] )

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. isRegExp 为 ? IsRegExp(searchString)。
  4. 如果 isRegExptrue,抛出 TypeError 异常。
  5. searchStr 为 ? ToString(searchString)。
  6. lenS 的长度。
  7. 如果 positionundefined,令 pos 为 0;否则令 pos 为 ? ToIntegerOrInfinity(position)。
  8. startclamping pos 在 0 和 len 之间的结果。
  9. searchLengthsearchStr 的长度。
  10. 如果 searchLength = 0,返回 true
  11. endstart + searchLength
  12. 如果 end > len,返回 false
  13. substringsubstring Sstartend
  14. 如果 substring 等于 searchStr,返回 true
  15. 返回 false
注 1

如果 searchString(转换为字符串)的码元序列与本对象(转换为字符串)从 position 开始的对应码元相同,则返回 true,否则返回 false

注 2

如果第一个参数是 RegExp 抛出异常,是为了允许后续标准版本定义支持此类参数值的扩展。

注 3

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.25 String.prototype.substring ( start, end )

该方法返回将此对象转换为字符串后的子串,从索引 start 开始,到但不包括字符串的索引 end(或若 endundefined,则直到字符串末尾)。结果是 String值,而不是 String 对象。

如果任一参数为 NaN 或负数,则用零替换;如果任一参数严格大于字符串长度,则用字符串长度替换。

如果 start 严格大于 end,则交换两者。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. lenS 的长度。
  4. intStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 endundefined,令 intEndlen;否则令 intEnd 为 ? ToIntegerOrInfinity(end)。
  6. finalStartclamping intStart 在 0 和 len 之间的结果。
  7. finalEndclamping intEnd 在 0 和 len 之间的结果。
  8. frommin(finalStart, finalEnd)。
  9. tomax(finalStart, finalEnd)。
  10. 返回 substring Sfromto

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.26 String.prototype.toLocaleLowerCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

其行为与 toLowerCase 相同,但旨在根据 宿主环境 当前区域设置的惯例产生区域敏感的结果。仅在少数(如土耳其语)该语言规则与常规 Unicode 大小写映射冲突的情况下才会有差异。

该方法的可选参数含义由 ECMA-402 规范定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.27 String.prototype.toLocaleUpperCase ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现未包含 ECMA-402 API,则使用以下规范:

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

其行为与 toUpperCase 相同,但旨在根据 宿主环境 当前区域设置的惯例产生区域敏感的结果。仅在少数(如土耳其语)该语言规则与常规 Unicode 大小写映射冲突的情况下才会有差异。

该方法的可选参数含义由 ECMA-402 规范定义;未包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.28 String.prototype.toLowerCase ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. sTextStringToCodePoints(S)。
  4. lowerText 为根据 Unicode 默认大小写转换算法对 sText 执行 toLowercase。
  5. LCodePointsToString(lowerText)。
  6. 返回 L

结果必须依据 Unicode 字符数据库中的区域无关大小写映射得出(这不仅包括 UnicodeData.txt 文件,还包括伴随的 SpecialCasing.txt 文件中所有区域无关的映射)。

注 1

某些码点的大小写映射可能产生多个码点。在这种情况下,结果字符串的长度可能与源字符串不同。由于 toUpperCasetoLowerCase 都具有上下文相关行为,这些方法并不对称。换言之,s.toUpperCase().toLowerCase() 不一定等于 s.toLowerCase()

注 2

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.29 String.prototype.toString ( )

调用该方法时,执行以下步骤:

  1. 返回 ? ThisStringValue(this 值)。

对于 String 对象,此方法恰好返回与 valueOf 方法相同的值。

22.1.3.30 String.prototype.toUpperCase ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

其行为与 String.prototype.toLowerCase 完全相同,只是字符串使用 Unicode 默认大小写转换的 toUppercase 算法进行映射。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.31 String.prototype.toWellFormed ( )

该方法返回此对象的字符串表示,将所有不是代理对一部分的前导代理项尾随代理项替换为 U+FFFD(替换字符)。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. S 为 ? ToString(O)。
  3. strLenS 的长度。
  4. k 为 0。
  5. result 为空字符串。
  6. 重复,直到 k < strLen
    1. cpCodePointAt(S, k)。
    2. 如果 cp.[[IsUnpairedSurrogate]]true,则
      1. result 设为 字符串拼接 result 和 0xFFFD(替换字符)的结果。
    3. 否则,
      1. result 设为 字符串拼接 resultUTF16EncodeCodePoint(cp.[[CodePoint]]) 的结果。
    4. k 设为 k + cp.[[CodeUnitCount]]
  7. 返回 result

22.1.3.32 String.prototype.trim ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. Sthis 值。
  2. 返回 ? TrimString(S, start+end)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.32.1 TrimString ( string, where )

抽象操作 TrimString 接收参数 stringECMAScript 语言值)和 wherestartendstart+end),返回字符串或抛出异常。它将 string 解释为 UTF-16 编码码点序列,如 6.1.4 规定。调用时执行以下步骤:

  1. str 为 ? RequireObjectCoercible(string)。
  2. S 为 ? ToString(str)。
  3. 如果 wherestart,则
    1. TS 去除前导空白后的字符串值。
  4. 否则若 whereend,则
    1. TS 去除尾随空白后的字符串值。
  5. 否则,
    1. 断言wherestart+end
    2. TS 去除前导和尾随空白后的字符串值。
  6. 返回 T

空白的定义为 WhiteSpaceLineTerminator 的并集。在判断 Unicode 码点是否属于 Unicode 一般类别 “Space_Separator” (“Zs”) 时,码元序列被解释为 6.1.4 规定的 UTF-16 编码码点序列。

22.1.3.33 String.prototype.trimEnd ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. Sthis 值。
  2. 返回 ? TrimString(S, end)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.34 String.prototype.trimStart ( )

该方法将 String 值作为 UTF-16 编码码点序列解释,如 6.1.4 中描述。

调用该方法时,执行以下步骤:

  1. Sthis 值。
  2. 返回 ? TrimString(S, start)。

此方法有意设计为泛型;它不要求其 this 值为 String 对象。因此,可以转移到其他类型的对象上作为方法使用。

22.1.3.35 String.prototype.valueOf ( )

调用该方法时,执行以下步骤:

  1. 返回 ? ThisStringValue(this 值)。

22.1.3.35.1 ThisStringValue ( value )

抽象操作 ThisStringValue 接收参数 valueECMAScript 语言值),返回字符串或抛出异常。调用时执行以下步骤:

  1. 如果 value 是 String,返回 value
  2. 如果 value 是对象value 具有 [[StringData]] 内部槽,则
    1. svalue.[[StringData]]
    2. 断言s 是 String
    3. 返回 s
  3. 抛出 TypeError 异常。

22.1.3.36 String.prototype [ %Symbol.iterator% ] ( )

该方法返回一个迭代器对象,用于遍历字符串值的每个码点,每次返回一个字符串值。

调用该方法时,执行以下步骤:

  1. O 为 ? RequireObjectCoercible(this 值)。
  2. s 为 ? ToString(O)。
  3. closure 为新的抽象闭包,无参数,捕获 s,并在被调用时执行以下步骤:
    1. lens 的长度。
    2. position 为 0。
    3. 重复,直到 position < len
      1. cpCodePointAt(s, position)。
      2. nextIndexposition + cp.[[CodeUnitCount]]
      3. resultStringsubstring spositionnextIndex
      4. position 设为 nextIndex
      5. 执行 ? GeneratorYield(CreateIteratorResultObject(resultString, false))。
    4. 返回 undefined
  4. 返回 CreateIteratorFromClosure(closure, "%StringIteratorPrototype%", %StringIteratorPrototype%)。

该方法的 "name" 属性值为 "[Symbol.iterator]"

22.1.4 String 实例的属性

String 实例是 String 特殊对象,并具有为此类对象规定的内部方法。String 实例继承自 String 原型对象 的属性。String 实例还具有 [[StringData]] 内部槽。[[StringData]] 内部槽是该 String 对象所表示的 String 值。

String 实例具有 "length" 属性,以及一组具有 整数索引名称的可枚举属性。

22.1.4.1 length

该 String 对象所表示的 String 值中的元素数量。

一旦 String 对象被初始化,此属性不可更改。它具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.1.5 String 迭代器对象

String 迭代器是表示对某个特定 String 实例对象的某次特定迭代的对象。String 迭代器对象没有命名的构造函数。而是通过调用 String 实例对象的某些方法创建 String 迭代器对象。

22.1.5.1 %StringIteratorPrototype% 对象

%StringIteratorPrototype% 对象:

22.1.5.1.1 %StringIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%StringIteratorPrototype%")。

22.1.5.1.2 %StringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "String Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2 RegExp(正则表达式)对象

RegExp 对象包含一个正则表达式和相关的标志(flags)。

正则表达式的形式和功能模仿了 Perl 5 编程语言中的正则表达式机制。

22.2.1 模式(Patterns)

RegExp 构造函数 对输入模式字符串应用以下语法。如果该语法无法将字符串解释为 Pattern 的展开,则会发生错误。

语法

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

每个 \u HexTrailSurrogate,其关联的 u HexLeadSurrogate 存在歧义时,应将其关联到最近且本来没有对应 \u HexTrailSurrogateu HexLeadSurrogate

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] 注 1

此处前两行等价于 CharacterClass。

ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~ 注 2

本节中的多项产生式在 B.1.2 节中给出了替代定义。

22.2.1.1 静态语义:早期错误(Static Semantics: Early Errors)

本节在 B.1.2.1 中有补充。

Pattern :: Disjunction QuantifierPrefix :: { DecimalDigits , DecimalDigits } Atom :: (? RegularExpressionModifiers : Disjunction ) Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction ) AtomEscape :: k GroupName AtomEscape :: DecimalEscape NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue CharacterClassEscape :: P{ UnicodePropertyValueExpression } CharacterClass :: [^ ClassContents ] NestedClass :: [^ ClassContents ] ClassSetRange :: ClassSetCharacter - ClassSetCharacter

22.2.1.2 静态语义:CountLeftCapturingParensWithin (node)

抽象操作 CountLeftCapturingParensWithin 接收参数 node(一个 解析节点),返回一个非负整数。它返回 node 中左捕获括号的数量。左捕获括号是任何与以下产生式的 ( 终结符匹配的 ( 模式字符:

Atom :: ( GroupSpecifieropt Disjunction )

本节在 B.1.2.2 中有补充。

调用时,执行以下步骤:

  1. 断言node正则表达式模式语法中的某个产生式的实例。
  2. 返回 node 内部所包含的以下解析节点的数量:
Atom :: ( GroupSpecifieropt Disjunction )

解析节点

22.2.1.3 静态语义:CountLeftCapturingParensBefore (node)

抽象操作 CountLeftCapturingParensBefore 接收参数 node(一个 解析节点),返回一个非负整数。它返回封闭模式中出现在 node 左侧的左捕获括号的数量。

本节在 B.1.2.2 中有补充。

调用时,执行以下步骤:

  1. 断言node正则表达式模式语法中的某个产生式的实例。
  2. pattern 为包含 nodePattern
  3. 返回 pattern 内部,出现在 node 之前或包含 node 的以下解析节点的数量:
Atom :: ( GroupSpecifieropt Disjunction )

解析节点

22.2.1.4 静态语义:MightBothParticipate (x, y)

抽象操作 MightBothParticipate 接收参数 x(一个 解析节点)和 y(一个 解析节点),返回布尔值。调用时,执行以下步骤:

  1. 断言xy 拥有同一个封闭的 Pattern
  2. 如果该封闭 Pattern 包含如下 Disjunction :: Alternative | Disjunction 解析节点,使得 x 包含于 Alternative 中且 y 包含于派生的 Disjunction 中,或者 x 包含于派生的 Disjunction 中且 y 包含于 Alternative 中,则返回 false
  3. 返回 true

22.2.1.5 静态语义:CapturingGroupNumber

语法定向操作 CapturingGroupNumber 无参数,返回正整数

本节在 B.1.2.1 中有补充。

在以下产生式中分段定义:

DecimalEscape :: NonZeroDigit
  1. 返回 NonZeroDigit 的 MV。
DecimalEscape :: NonZeroDigit DecimalDigits
  1. nDecimalDigits 中码点的数量。
  2. 返回 (NonZeroDigit 的 MV × 10nDecimalDigits 的 MV)。

NonZeroDigit 的 MV” 和 “DecimalDigits 的 MV” 的定义见 12.9.3

22.2.1.6 静态语义:IsCharacterClass

语法定向操作 IsCharacterClass 无参数,返回布尔值。

本节在 B.1.2.3 中有补充。

在以下产生式中分段定义:

ClassAtom :: - ClassAtomNoDash :: SourceCharacter 但不是 \]- 之一 ClassEscape :: b - CharacterEscape
  1. 返回 false
ClassEscape :: CharacterClassEscape
  1. 返回 true

22.2.1.7 静态语义:CharacterValue

语法定向操作 CharacterValue 无参数,返回非负整数

注 1

本节在 B.1.2.4 中有补充。

在以下产生式中分段定义:

ClassAtom :: -
  1. 返回 U+002D(连字符 HYPHEN-MINUS)的数值。
ClassAtomNoDash :: SourceCharacter但不是 \]- 之一
  1. chSourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassEscape :: b
  1. 返回 U+0008(退格 BACKSPACE)的数值。
ClassEscape :: -
  1. 返回 U+002D(连字符 HYPHEN-MINUS)的数值。
CharacterEscape :: ControlEscape
  1. 按照 表 67 返回数值。
表 67: ControlEscape 码点数值
ControlEscape 数值 码点 Unicode 名称 符号
t 9 U+0009 CHARACTER TABULATION <HT>
n 10 U+000A LINE FEED (LF) <LF>
v 11 U+000B LINE TABULATION <VT>
f 12 U+000C FORM FEED (FF) <FF>
r 13 U+000D CARRIAGE RETURN (CR) <CR>
CharacterEscape :: c AsciiLetter
  1. chAsciiLetter 匹配的码点。
  2. ich 的数值。
  3. 返回 i 除以 32 的余数。
CharacterEscape :: 0 [lookahead ∉ DecimalDigit]
  1. 返回 U+0000(NULL)的数值。
注 2

\0 表示 <NUL> 字符,且不能后跟十进制数字。

CharacterEscape :: HexEscapeSequence
  1. 返回 HexEscapeSequence 的 MV。
RegExpUnicodeEscapeSequence :: u HexLeadSurrogate \u HexTrailSurrogate
  1. leadCharacterValue of HexLeadSurrogate
  2. trailCharacterValue of HexTrailSurrogate
  3. cpUTF16SurrogatePairToCodePoint(lead, trail)。
  4. 返回 cp 的数值。
RegExpUnicodeEscapeSequence :: u Hex4Digits
  1. 返回 Hex4Digits 的 MV。
RegExpUnicodeEscapeSequence :: u{ CodePoint }
  1. 返回 CodePoint 的 MV。
HexLeadSurrogate :: Hex4Digits HexTrailSurrogate :: Hex4Digits HexNonSurrogate :: Hex4Digits
  1. 返回 Hex4Digits 的 MV。
CharacterEscape :: IdentityEscape
  1. chIdentityEscape 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: SourceCharacter但不是 ClassSetSyntaxCharacter
  1. chSourceCharacter 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \ ClassSetReservedPunctuator
  1. chClassSetReservedPunctuator 匹配的码点。
  2. 返回 ch 的数值。
ClassSetCharacter :: \b
  1. 返回 U+0008(退格 BACKSPACE)的数值。

22.2.1.8 静态语义:MayContainStrings

语法定向操作 MayContainStrings 无参数,返回布尔值。它在以下产生式中分段定义:

CharacterClassEscape :: d D s S w W P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue NestedClass :: [^ ClassContents ] ClassContents :: [empty] NonemptyClassRanges ClassSetOperand :: ClassSetCharacter
  1. 返回 false
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. 如果 source text matched by LoneUnicodePropertyNameOrValue表 71“属性名”列中列出的字符串的二进制属性,则返回 true
  2. 返回 false
ClassUnion :: ClassSetRange ClassUnionopt
  1. 如果 ClassUnion 存在,返回 MayContainStrings of ClassUnion
  2. 返回 false
ClassUnion :: ClassSetOperand ClassUnionopt
  1. 如果 MayContainStrings of ClassSetOperandtrue,返回 true
  2. 如果 ClassUnion 存在,返回 MayContainStrings of ClassUnion
  3. 返回 false
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. 如果 MayContainStrings of 第一个 ClassSetOperandfalse,返回 false
  2. 如果 MayContainStrings of 第二个 ClassSetOperandfalse,返回 false
  3. 返回 true
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. 如果 MayContainStrings of ClassIntersectionfalse,返回 false
  2. 如果 MayContainStrings of ClassSetOperandfalse,返回 false
  3. 返回 true
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. 返回第一个 MayContainStrings of ClassSetOperand
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. 返回 MayContainStrings of ClassSubtraction
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. 如果 MayContainStrings of ClassStringtrue,返回 true
  2. 返回 MayContainStrings of ClassStringDisjunctionContents
ClassString :: [empty]
  1. 返回 true
ClassString :: NonEmptyClassString
  1. 返回 MayContainStrings of NonEmptyClassString
NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt
  1. 如果 NonEmptyClassString 存在,返回 true
  2. 返回 false

22.2.1.9 静态语义:GroupSpecifiersThatMatch (thisGroupName)

抽象操作 GroupSpecifiersThatMatch 接收参数 thisGroupName(一个 GroupName 解析节点),返回 List 类型的 GroupSpecifier 解析节点。调用时,执行如下步骤:

  1. nameCapturingGroupName of thisGroupName
  2. pattern 为包含 thisGroupNamePattern
  3. result 为一个新的空 List
  4. 对于 pattern 包含的每个 GroupSpecifier gs,执行:
    1. 如果 gsCapturingGroupName 等于 name,则:
      1. gs 添加至 result
  5. 返回 result

22.2.1.10 静态语义:CapturingGroupName

语法定向操作 CapturingGroupName 无参数,返回字符串。它在以下产生式中分段定义:

GroupName :: < RegExpIdentifierName >
  1. idTextUnescapedRegExpIdentifierCodePoints of RegExpIdentifierName
  2. 返回 CodePointsToString(idTextUnescaped)。

22.2.1.11 静态语义:RegExpIdentifierCodePoints

语法定向操作 RegExpIdentifierCodePoints 无参数,返回码点 List。它在以下产生式中分段定义:

RegExpIdentifierName :: RegExpIdentifierStart
  1. cpRegExpIdentifierCodePoint of RegExpIdentifierStart
  2. 返回 « cp »。
RegExpIdentifierName :: RegExpIdentifierName RegExpIdentifierPart
  1. cps 为派生的 RegExpIdentifierCodePoints of RegExpIdentifierName
  2. cpRegExpIdentifierCodePoint of RegExpIdentifierPart
  3. 返回 list-concatenation of cps 和 « cp »。

22.2.1.12 静态语义:RegExpIdentifierCodePoint

语法定向操作 RegExpIdentifierCodePoint 无参数,返回码点。它在以下产生式中分段定义:

RegExpIdentifierStart :: IdentifierStartChar
  1. 返回 IdentifierStartChar 匹配的码点。
RegExpIdentifierPart :: IdentifierPartChar
  1. 返回 IdentifierPartChar 匹配的码点。
RegExpIdentifierStart :: \ RegExpUnicodeEscapeSequence RegExpIdentifierPart :: \ RegExpUnicodeEscapeSequence
  1. 返回数值为 CharacterValue of RegExpUnicodeEscapeSequence 的码点。
RegExpIdentifierStart :: UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart :: UnicodeLeadSurrogate UnicodeTrailSurrogate
  1. leadUnicodeLeadSurrogate 匹配的码点的数值所对应的码元。
  2. trailUnicodeTrailSurrogate 匹配的码点的数值所对应的码元。
  3. 返回 UTF16SurrogatePairToCodePoint(lead, trail)。

22.2.2 模式语义(Pattern Semantics)

正则表达式模式会按照下述过程被转换为一个 抽象闭包(Abstract Closure)。实现可以使用比下文所列更高效的算法,只要结果一致。该 抽象闭包 用作 RegExp 对象的 [[RegExpMatcher]] 内部槽的值。

如果一个 Pattern 的关联标志既不包含 u 也不包含 v,则它是 BMP 模式。否则,它是 Unicode 模式。BMP 模式会针对被解释为由处于基本多文种平面(BMP)范围内的 Unicode 码点组成的 16 位值序列的字符串进行匹配。Unicode 模式则针对被解释为用 UTF-16 编码的 Unicode 码点序列的字符串进行匹配。在描述 BMP 模式行为时,“character” 表示单个 16 位的 Unicode BMP 码点。在描述 Unicode 模式行为时,“character” 表示一个 UTF-16 编码的码点(6.1.4)。无论哪种情况,“character value” 都指对应非编码码点的数值。

Pattern 的语法和语义定义为其源文本为一个 List,其中每个元素为 SourceCharacter,对应一个 Unicode 码点。如果 BMP 模式包含了非 BMP 的 SourceCharacter,则整个模式会被用 UTF-16 编码,并将该编码的各个码元作为 List 的元素。

例如,假设一个模式在源文本中表示为单个非 BMP 字符 U+1D11E(MUSICAL SYMBOL G CLEF)。作为 Unicode 模式解释时,它是一个仅包含该码点 U+1D11E 的元素(字符)List。然而,作为 BMP 模式解释时,它会首先被 UTF-16 编码,得到两个元素的 List,其码元分别为 0xD834 和 0xDD1E。

模式会以 ECMAScript 字符串值的形式传递给 RegExp 构造函数,其中非 BMP 字符已经用 UTF-16 编码。例如,该 MUSICAL SYMBOL G CLEF 单字符模式,表达为字符串值时,是长度为 2 的字符串,其元素为 0xD834 和 0xDD1E 码元。因此,若作为包含两个模式字符的 BMP 模式处理,不需要再对字符串做转换;但若作为 Unicode 模式处理,则需用 UTF16SurrogatePairToCodePoint 得到仅含一个模式字符(码点 U+1D11E)的 List

实现不一定真的需要进行这些 UTF-16 的转换,但本规范要求,模式匹配的语义要如同进行了这些转换一样。

22.2.2.1 符号说明(Notation)

下述描述使用以下内部数据结构:

  • CharSetElement(字符集元素)是以下两种实体之一:
    • rer.[[UnicodeSets]]false,CharSetElement 就是前述“模式语义”意义下的字符。
    • rer.[[UnicodeSets]]true,CharSetElement 是一个序列,其元素为“模式语义”意义下的字符。包括空序列、单字符序列和多字符序列。为了方便,处理这类 CharSetElement 时,单个字符和单字符序列可以互换。
  • CharSet(字符集)是 CharSetElement 的数学集合。
  • CaptureRange(捕获范围)是一个 Record { [[StartIndex]], [[EndIndex]] },表示捕获所包含的字符范围,其中 [[StartIndex]]整数,表示 Input 中范围的起始索引(包含),[[EndIndex]]整数,表示 Input 中范围的结束索引(不包含)。任何 CaptureRange 都必须满足 [[StartIndex]][[EndIndex]]
  • MatchState(匹配状态)是一个 Record { [[Input]], [[EndIndex]], [[Captures]] },其中 [[Input]] 是待匹配字符串的字符 List[[EndIndex]]整数[[Captures]] 是一个 List,每个元素对应模式中的一个 左捕获括号MatchStates 用于表达正则表达式匹配算法中的部分匹配状态。[[EndIndex]] 是当前为止最后一个已匹配输入字符的索引加一,[[Captures]] 保存捕获括号的结果。n[[Captures]] 元素,要么是 CaptureRange,表示第 n 个捕获括号捕获的范围,要么为 undefined 表示还未到达。由于回溯,匹配过程中可能同时存在多个 MatchStates
  • MatcherContinuation(匹配延续)是一个 抽象闭包,接收一个 MatchState 参数,返回一个 MatchStatefailureMatcherContinuation 试图将模式剩余部分(由闭包捕获的值指定)与 Input 匹配,从当前 MatchState 状态开始。如果匹配成功,返回最终到达的 MatchState,否则返回 failure
  • Matcher(匹配器)是一个 抽象闭包,接收两个参数——MatchStateMatcherContinuation,返回 MatchStatefailureMatcher 试图将模式的某一中间子模式(由闭包捕获的值指定)与 MatchState[[Input]] 匹配,从传入的中间状态开始。MatcherContinuation 参数应为匹配剩余模式的闭包。匹配子模式获得新的 MatchState 后,Matcher 会在此状态上调用 MatcherContinuation 检查剩余模式是否也能匹配。如果可以,返回 MatchState;否则,匹配器可能会在其选择点尝试不同的选择,不断调用 MatcherContinuation,直到成功或无可能性为止。

22.2.2.1.1 RegExp 记录(RegExp Records)

RegExp Record 是一个 Record,用于存储 RegExp 在编译及可能的匹配期间需要的信息。

它包含如下字段:

表 68: RegExp Record 字段
字段名 含义
[[IgnoreCase]] 布尔值 指示 RegExp 标志中是否出现 "i"
[[Multiline]] 布尔值 指示 RegExp 标志中是否出现 "m"
[[DotAll]] 布尔值 指示 RegExp 标志中是否出现 "s"
[[Unicode]] 布尔值 指示 RegExp 标志中是否出现 "u"
[[UnicodeSets]] 布尔值 指示 RegExp 标志中是否出现 "v"
[[CapturingGroupsCount]] 非负整数 RegExp 模式中的 左捕获括号 的数量

22.2.2.2 运行时语义:CompilePattern

语法定向操作 CompilePattern 接收参数 rer(一个 RegExp Record),返回一个 抽象闭包(Abstract Closure),该闭包接收一个字符 List 和一个非负 整数,返回一个 MatchStatefailure。它在以下产生式中分段定义:

Pattern :: Disjunction
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 抽象闭包,参数为 (Input, index),捕获 rerm,调用时执行以下步骤:
    1. 断言Input 为字符 List
    2. 断言:0 ≤ indexInput 的元素数量。
    3. c 为一个新 MatcherContinuation,参数 (y),不捕获任何内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. caprer.[[CapturingGroupsCount]]undefinedList,索引从 1 到 rer.[[CapturingGroupsCount]]
    5. xMatchState { [[Input]]: Input, [[EndIndex]]: index, [[Captures]]: cap }。
    6. 返回 m(x, c)。

Pattern 会被编译为 抽象闭包(Abstract Closure)RegExpBuiltinExec 可以将该过程应用于字符 List 及其偏移量,以判断模式是否会正好从该偏移处开始匹配,并在匹配时获得捕获括号的值。本节算法允许编译过程中抛出 SyntaxError;但一旦编译成功,匹配时除非发生实现相关异常(如内存溢出)不会抛出异常。

22.2.2.3 运行时语义:CompileSubpattern

语法定向操作 CompileSubpattern 接收参数 rer(一个 RegExp Record)和 directionforwardbackward),返回一个 Matcher

注 1

本节在 B.1.2.5 中有补充。

在以下产生式中分段定义:

Disjunction :: Alternative | Disjunction
  1. m1CompileSubpattern of Alternative,参数为 rerdirection
  2. m2CompileSubpattern of Disjunction,参数为 rerdirection
  3. 返回 MatchTwoAlternatives(m1, m2)。
注 2

| 正则表达式操作符分隔两个备选项。模式首先尝试匹配左侧 Alternative(后接正则表达式剩余部分);如果失败,则尝试匹配右侧 Disjunction(后接剩余部分)。如果左侧 Alternative、右侧 Disjunction 和剩余部分都有选择点,则会先穷尽剩余部分的所有选择,再移动到右侧。若左侧所有选择用尽,则会尝试右侧。被 | 跳过的部分中的捕获括号,其值为 undefined 而非字符串。例如:

/a|ab/.exec("abc")

返回结果为 "a" 而非 "ab"。再例如:

/((a)|(ab))((c)|(bc))/.exec("abc")

返回数组:

["abc", "a", "a", undefined, "bc", undefined, "bc"]

而不是:

["abc", "ab", undefined, "ab", "c", "c", undefined]

两个备选项的尝试顺序与 direction 的值无关。

Alternative :: [empty]
  1. 返回 EmptyMatcher()。
Alternative :: Alternative Term
  1. m1CompileSubpattern of Alternative,参数为 rerdirection
  2. m2CompileSubpattern of Term,参数为 rerdirection
  3. 返回 MatchSequence(m1, m2, direction)。
注 3

连续的 Term 会尝试同时匹配 Input 的连续部分。当 directionforward 时,若左、右和剩余部分都有选择点,则会先穷尽剩余、再穷尽右侧、最后再穷尽左侧的选择。当 directionbackward 时,左、右的顺序交换。

Term :: Assertion
  1. 返回 CompileAssertion of Assertion,参数为 rer
注 4

所得 Matcherdirection 无关。

Term :: Atom
  1. 返回 CompileAtom of Atom,参数为 rerdirection
Term :: Atom Quantifier
  1. mCompileAtom of Atom,参数为 rerdirection
  2. qCompileQuantifier of Quantifier
  3. 断言q.[[Min]]q.[[Max]]
  4. parenIndexCountLeftCapturingParensBefore(Term)。
  5. parenCountCountLeftCapturingParensWithin(Atom)。
  6. 返回一个新 Matcher,参数为 (x, c),捕获 mqparenIndexparenCount,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. 返回 RepeatMatcher(m, q.[[Min]], q.[[Max]], q.[[Greedy]], x, c, parenIndex, parenCount)。

22.2.2.3.1 RepeatMatcher (m, min, max, greedy, x, c, parenIndex, parenCount)

抽象操作 RepeatMatcher 接收参数 m(一个 Matcher)、min(非负 整数)、max(非负 整数 或 +∞)、greedy(布尔值)、xMatchState)、cMatcherContinuation)、parenIndex(非负 整数)、parenCount(非负 整数),返回一个 MatchStatefailure。调用时执行以下步骤:

  1. 如果 max = 0,返回 c(x)。
  2. d 为一个新 MatcherContinuation,参数 (y),捕获 mminmaxgreedyxcparenIndexparenCount,调用时:
    1. 断言yMatchState
    2. 如果 min = 0 且 y.[[EndIndex]] = x.[[EndIndex]],返回 failure
    3. 如果 min = 0,令 min2 为 0;否则,令 min2min - 1。
    4. 如果 max = +∞,令 max2 为 +∞;否则,令 max2max - 1。
    5. 返回 RepeatMatcher(m, min2, max2, greedy, y, c, parenIndex, parenCount)。
  3. capx.[[Captures]] 的副本。
  4. 对于 整数 k,在 闭区间 parenIndex + 1 到 parenIndex + parenCount,令 cap[k] = undefined
  5. Inputx.[[Input]]
  6. ex.[[EndIndex]]
  7. xrMatchState { [[Input]]: Input, [[EndIndex]]: e, [[Captures]]: cap }。
  8. 如果 min ≠ 0,返回 m(xr, d)。
  9. 如果 greedyfalse,则:
    1. zc(x)。
    2. 如果 z 不为 failure,返回 z
    3. 返回 m(xr, d)。
  10. zm(xr, d)。
  11. 如果 z 不为 failure,返回 z
  12. 返回 c(x)。
注 1

一个 Atom 后跟 Quantifier 时,会根据 Quantifier 指定的次数重复。Quantifier 可以是非贪婪的(尽量少匹配)或贪婪的(尽量多匹配)。重复的是 Atom 的模式本身,不同重复可匹配不同的输入子串。

注 2

如果 Atom 和剩余部分都有选择点,会先尽量多(或少,若非贪婪)匹配 Atom,再穷尽剩余选择,然后再回溯到上一次重复。可以用这种选择点顺序写出求最大公约数的正则表达式。

注 3

RepeatMatcher 的 步骤 4 每次重复时都会清除 Atom 的捕获结果。

注 4

RepeatMatcher 的 2.b 指出:当已满足最小重复次数时,若 Atom 匹配空字符串,则不再继续重复,防止无限循环。

22.2.2.3.2 EmptyMatcher ( )

抽象操作 EmptyMatcher 无参数,返回一个 Matcher。调用时执行以下步骤:

  1. 返回一个新 Matcher,参数 (x, c),不捕获任何内容,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. 返回 c(x)。

22.2.2.3.3 MatchTwoAlternatives (m1, m2)

抽象操作 MatchTwoAlternatives 接收参数 m1Matcher)和 m2Matcher),返回一个 Matcher。调用时执行以下步骤:

  1. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. rm1(x, c)。
    4. rfailure,返回 r
    5. 返回 m2(x, c)。

22.2.2.3.4 MatchSequence (m1, m2, direction)

抽象操作 MatchSequence 接收参数 m1Matcher)、m2Matcher)、directionforwardbackward),返回一个 Matcher。调用时执行以下步骤:

  1. 如果 directionforward,则:
    1. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
      1. 断言xMatchState
      2. 断言cMatcherContinuation
      3. d 为一个新 MatcherContinuation,参数 (y),捕获 cm2,调用时:
        1. 断言yMatchState
        2. 返回 m2(y, c)。
      4. 返回 m1(x, d)。
  2. 否则:
    1. 断言directionbackward
    2. 返回一个新 Matcher,参数 (x, c),捕获 m1m2,调用时:
      1. 断言xMatchState
      2. 断言cMatcherContinuation
      3. d 为一个新 MatcherContinuation,参数 (y),捕获 cm1,调用时:
        1. 断言yMatchState
        2. 返回 m1(y, c)。
      4. 返回 m2(x, d)。

22.2.2.4 运行时语义:CompileAssertion

语法定向操作 CompileAssertion 接收参数 rerRegExp Record),返回一个 Matcher

注 1

本节在 B.1.2.6 中有补充。

在以下产生式中分段定义:

Assertion :: ^
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. 如果 e = 0,或 rer.[[Multiline]]trueInput[e - 1] 匹配 LineTerminator,则:
      1. 返回 c(x)。
    6. 返回 failure
注 2

即使正则表达式使用 y 标志,^ 也只会在 Input 开头或(若 rer.[[Multiline]]true)行首匹配。

Assertion :: $
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. InputLength = Input 的元素数量。
    6. 如果 e = InputLength,或 rer.[[Multiline]]trueInput[e] 匹配 LineTerminator,则:
      1. 返回 c(x)。
    7. 返回 failure
Assertion :: \b
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. a = IsWordChar(rer, Input, e - 1)。
    6. b = IsWordChar(rer, Input, e)。
    7. 如果 atruebfalse,或 afalsebtrue,返回 c(x)。
    8. 返回 failure
Assertion :: \B
  1. 返回一个新 Matcher,参数 (x, c),捕获 rer,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. a = IsWordChar(rer, Input, e - 1)。
    6. b = IsWordChar(rer, Input, e)。
    7. 如果 ab 同为 true 或同为 false,返回 c(x)。
    8. 返回 failure
Assertion :: (?= Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 断言rMatchState
    7. cap = r.[[Captures]]
    8. Input = x.[[Input]]
    9. xe = x.[[EndIndex]]
    10. zMatchState { [[Input]]: Input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 c(z)。
注 3

形式 (?= Disjunction ) 表示零宽度正向先行断言。其内部模式需在当前位置匹配成功,但当前位置不会推进。lookahead 内部无回溯。

Assertion :: (?! Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerforward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 返回 c(x)。
注 4

形式 (?! Disjunction ) 表示零宽度负向先行断言。其内部模式需在当前位置匹配失败。

Assertion :: (?<= Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerbackward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 断言rMatchState
    7. cap = r.[[Captures]]
    8. Input = x.[[Input]]
    9. xe = x.[[EndIndex]]
    10. zMatchState { [[Input]]: Input, [[EndIndex]]: xe, [[Captures]]: cap }。
    11. 返回 c(z)。
Assertion :: (?<! Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerbackward
  2. 返回一个新 Matcher,参数 (x, c),捕获 m,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),不捕获内容,调用时:
      1. 断言yMatchState
      2. 返回 y
    4. rm(x, d)。
    5. rfailure,返回 failure
    6. 返回 c(x)。

22.2.2.4.1 IsWordChar (rer, Input, e)

抽象操作 IsWordChar 接收参数 rerRegExp Record)、Input(字符 List)、e整数),返回布尔值。调用时执行以下步骤:

  1. InputLength = Input 的元素数量。
  2. 如果 e = -1 或 e = InputLength,返回 false
  3. c = Input[e]。
  4. 如果 WordCharacters(rer) 包含 c,返回 true
  5. 返回 false

22.2.2.5 运行时语义:CompileQuantifier

语法定向操作 CompileQuantifier 无参数,返回一个包含字段 [[Min]](非负 整数)、[[Max]](非负 整数 或 +∞)、[[Greedy]](布尔值)的 Record。在以下产生式中分段定义:

Quantifier :: QuantifierPrefix
  1. qpCompileQuantifierPrefix of QuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: true }。
Quantifier :: QuantifierPrefix ?
  1. qpCompileQuantifierPrefix of QuantifierPrefix
  2. 返回 Record { [[Min]]: qp.[[Min]], [[Max]]: qp.[[Max]], [[Greedy]]: false }。

22.2.2.6 运行时语义:CompileQuantifierPrefix

语法定向操作 CompileQuantifierPrefix 无参数,返回包含 [[Min]](非负 整数)、[[Max]](非负 整数 或 +∞)字段的 Record。在以下产生式中分段定义:

QuantifierPrefix :: *
  1. 返回 Record { [[Min]]: 0, [[Max]]: +∞ }。
QuantifierPrefix :: +
  1. 返回 Record { [[Min]]: 1, [[Max]]: +∞ }。
QuantifierPrefix :: ?
  1. 返回 Record { [[Min]]: 0, [[Max]]: 1 }。
QuantifierPrefix :: { DecimalDigits }
  1. iDecimalDigits 的 MV(见 12.9.3)。
  2. 返回 Record { [[Min]]: i, [[Max]]: i }。
QuantifierPrefix :: { DecimalDigits ,}
  1. iDecimalDigits 的 MV。
  2. 返回 Record { [[Min]]: i, [[Max]]: +∞ }。
QuantifierPrefix :: { DecimalDigits , DecimalDigits }
  1. i 为第一个 DecimalDigits 的 MV。
  2. j 为第二个 DecimalDigits 的 MV。
  3. 返回 Record { [[Min]]: i, [[Max]]: j }。

22.2.2.7 运行时语义:CompileAtom

语法定向操作 CompileAtom 接收参数 rerRegExp Record)和 directionforwardbackward),返回 Matcher

注 1

本节在 B.1.2.7 中有补充。

在以下产生式中分段定义:

Atom :: PatternCharacter
  1. chPatternCharacter 匹配的字符。
  2. A 为仅包含字符 ch 的单元素 CharSet
  3. 返回 CharacterSetMatcher(rer, A, false, direction)。
Atom :: .
  1. AAllCharacters(rer)。
  2. 如果 rer.[[DotAll]] 不为 true,则:
    1. A 中移除所有 LineTerminator 产生式右侧的码点对应的字符。
  3. 返回 CharacterSetMatcher(rer, A, false, direction)。
Atom :: CharacterClass
  1. ccCompileCharacterClass of CharacterClass,参数为 rer
  2. cs = cc.[[CharSet]]
  3. 如果 rer.[[UnicodeSets]]false,或 cs 的所有 CharSetElement 都是单字符(包括 cs 为空),则返回 CharacterSetMatcher(rer, cs, cc.[[Invert]], direction)。
  4. 断言cc.[[Invert]]false
  5. lmMatchers 的空 List
  6. 对于 cs 中每个包含多个字符的 CharSetElement s(按长度降序遍历),执行:
    1. cs2 为仅包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(rer, cs2, false, direction)。
    3. 对于 s 中每个码点 c1(从倒数第二个码点开始反向遍历),执行:
      1. cs1 为仅包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(rer, cs1, false, direction)。
      3. m2 = MatchSequence(m1, m2, direction)。
    4. m2 添加到 lm
  7. singlescs 中所有单字符 CharSetElement 组成的 CharSet
  8. CharacterSetMatcher(rer, singles, false, direction) 添加到 lm
  9. 如果 cs 包含空序列,则将 EmptyMatcher() 添加到 lm
  10. m2lm 的最后一个 Matcher
  11. 对于 lm 中每个 Matcher m1(从倒数第二个元素开始反向遍历),执行:
    1. m2 = MatchTwoAlternatives(m1, m2)。
  12. 返回 m2
Atom :: ( GroupSpecifieropt Disjunction )
  1. mCompileSubpattern of Disjunction,参数为 rerdirection
  2. parenIndex = CountLeftCapturingParensBefore(Atom)。
  3. 返回一个新 Matcher,参数 (x, c),捕获 directionmparenIndex,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. d 为一个新 MatcherContinuation,参数 (y),捕获 xcdirectionparenIndex,调用时:
      1. 断言yMatchState
      2. capy.[[Captures]] 的副本。
      3. Input = x.[[Input]]
      4. xe = x.[[EndIndex]]
      5. ye = y.[[EndIndex]]
      6. 如果 directionforward,则:
        1. 断言xeye
        2. rCaptureRange { [[StartIndex]]: xe, [[EndIndex]]: ye }。
      7. 否则:
        1. 断言directionbackward
        2. 断言yexe
        3. rCaptureRange { [[StartIndex]]: ye, [[EndIndex]]: xe }。
      8. 设置 cap[parenIndex + 1] = r
      9. zMatchState { [[Input]]: Input, [[EndIndex]]: ye, [[Captures]]: cap }。
      10. 返回 c(z)。
    4. 返回 m(x, d)。
注 2

形如 ( Disjunction ) 的括号既用于分组,也用于保存匹配结果。可以通过反向引用、替换字符串或结果数组使用该结果。用 (?: ... ) 可禁用捕获行为。

Atom :: (? RegularExpressionModifiers : Disjunction )
  1. addModifierssource text matched by RegularExpressionModifiers
  2. removeModifiers 为空字符串。
  3. modifiedRer = UpdateModifiers(rer, CodePointsToString(addModifiers), removeModifiers)。
  4. 返回 CompileSubpattern of Disjunction,参数为 modifiedRerdirection
Atom :: (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction )
  1. addModifierssource text matched by 第一个 RegularExpressionModifiers
  2. removeModifierssource text matched by 第二个 RegularExpressionModifiers
  3. modifiedRer = UpdateModifiers(rer, CodePointsToString(addModifiers), CodePointsToString(removeModifiers))。
  4. 返回 CompileSubpattern of Disjunction,参数为 modifiedRerdirection
AtomEscape :: DecimalEscape
  1. nCapturingGroupNumber of DecimalEscape
  2. 断言nrer.[[CapturingGroupsCount]]
  3. 返回 BackreferenceMatcher(rer, « n », direction)。
注 3

形如 \ 后跟非零十进制数字 n 的转义序列,匹配第 n 个捕获括号的结果。括号数不足 n 是错误。若 n 个括号有但第 n 个未捕获内容,则反向引用总是成功。

AtomEscape :: CharacterEscape
  1. cvCharacterValue of CharacterEscape
  2. ch 为字符值为 cv 的字符。
  3. A 为仅包含字符 ch 的单元素 CharSet
  4. 返回 CharacterSetMatcher(rer, A, false, direction)。
AtomEscape :: CharacterClassEscape
  1. csCompileToCharSet of CharacterClassEscape,参数为 rer
  2. 如果 rer.[[UnicodeSets]]false,或 cs 的所有 CharSetElement 都是单字符(包括 cs 为空),则返回 CharacterSetMatcher(rer, cs, false, direction)。
  3. lmMatchers 的空 List
  4. 对于 cs 中每个包含多个字符的 CharSetElement s(按长度降序遍历),执行:
    1. cs2 为仅包含 s 最后一个码点的单元素 CharSet
    2. m2CharacterSetMatcher(rer, cs2, false, direction)。
    3. 对于 s 中每个码点 c1(从倒数第二个码点开始反向遍历),执行:
      1. cs1 为仅包含 c1 的单元素 CharSet
      2. m1CharacterSetMatcher(rer, cs1, false, direction)。
      3. m2 = MatchSequence(m1, m2, direction)。
    4. m2 添加到 lm
  5. singlescs 中所有单字符 CharSetElement 组成的 CharSet
  6. CharacterSetMatcher(rer, singles, false, direction) 添加到 lm
  7. 如果 cs 包含空序列,则将 EmptyMatcher() 添加到 lm
  8. m2lm 的最后一个 Matcher
  9. 对于 lm 中每个 Matcher m1(从倒数第二个元素开始反向遍历),执行:
    1. m2 = MatchTwoAlternatives(m1, m2)。
  10. 返回 m2
AtomEscape :: k GroupName
  1. matchingGroupSpecifiersGroupSpecifiersThatMatch(GroupName)。
  2. parenIndices 为一个新的空 List
  3. 对于 matchingGroupSpecifiers 中的每一个 GroupSpecifier groupSpecifier,执行:
    1. parenIndex = CountLeftCapturingParensBefore(groupSpecifier)。
    2. parenIndex 添加到 parenIndices
  4. 返回 BackreferenceMatcher(rer, parenIndices, direction)。

22.2.2.7.1 CharacterSetMatcher (rer, A, invert, direction)

抽象操作 CharacterSetMatcher 接收参数 rerRegExp Record)、ACharSet)、invert(布尔值)、directionforwardbackward),返回 Matcher。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]true,则:
    1. 断言invertfalse
    2. 断言A 的每个 CharSetElement 都是单字符。
  2. 返回一个新 Matcher,参数 (x, c),捕获 rerAinvertdirection,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. e = x.[[EndIndex]]
    5. directionforward,令 f = e + 1。
    6. 否则,令 f = e - 1。
    7. InputLength = Input 的元素数量。
    8. f < 0 或 f > InputLength,返回 failure
    9. index = min(e, f)。
    10. ch = Input[index]。
    11. cc = Canonicalize(rer, ch)。
    12. 如果存在 A 中仅含字符 aCharSetElement,且 Canonicalize(rer, a) 等于 cc,则 found = true,否则 found = false
    13. invertfalsefoundfalse,返回 failure
    14. inverttruefoundtrue,返回 failure
    15. cap = x.[[Captures]]
    16. y = MatchState { [[Input]]: Input, [[EndIndex]]: f, [[Captures]]: cap }。
    17. 返回 c(y)。

22.2.2.7.2 BackreferenceMatcher (rer, ns, direction)

抽象操作 BackreferenceMatcher 接收参数 rerRegExp Record)、ns(正 整数List)、directionforwardbackward),返回 Matcher。调用时执行如下步骤:

  1. 返回一个新 Matcher,参数 (x, c),捕获 rernsdirection,调用时:
    1. 断言xMatchState
    2. 断言cMatcherContinuation
    3. Input = x.[[Input]]
    4. cap = x.[[Captures]]
    5. r = undefined
    6. 对于 ns 中的每个 整数 n,执行:
      1. cap[n] 非 undefined,则:
        1. 断言rundefined
        2. r = cap[n]。
    7. rundefined,返回 c(x)。
    8. e = x.[[EndIndex]]
    9. rs = r.[[StartIndex]]
    10. re = r.[[EndIndex]]
    11. len = re - rs
    12. directionforward,令 f = e + len
    13. 否则,令 f = e - len
    14. InputLength = Input 的元素数量。
    15. f < 0 或 f > InputLength,返回 failure
    16. g = min(e, f)。
    17. 若存在 0(含)到 len(不含)间的 整数 i,使得 Canonicalize(rer, Input[rs+i]) ≠ Canonicalize(rer, Input[g+i]),返回 failure
    18. y = MatchState { [[Input]]: Input, [[EndIndex]]: f, [[Captures]]: cap }。
    19. 返回 c(y)。

22.2.2.7.3 Canonicalize (rer, ch)

抽象操作 Canonicalize 接收参数 rerRegExp Record)、ch(字符),返回一个字符。调用时执行如下步骤:

  1. HasEitherUnicodeFlag(rer) 为 truerer.[[IgnoreCase]]true,则:
    1. CaseFolding.txt 提供了 ch 的简单或通用大小写折叠映射,则返回应用该映射后的 ch
    2. 返回 ch
  2. rer.[[IgnoreCase]]false,返回 ch
  3. 断言ch 是 UTF-16 码元。
  4. cpch 的数值对应的码点。
  5. u 为根据 Unicode 默认大小写转换算法 toUppercase(« cp »)。
  6. uStr = CodePointsToString(u)。
  7. uStr 长度 ≠ 1,返回 ch
  8. cu = uStr 的唯一码元。
  9. ch 数值 ≥ 128 且 cu 数值 < 128,返回 ch
  10. 返回 cu

HasEitherUnicodeFlag(rer) 为 true 且大小写不敏感时,所有字符都用 Unicode 标准的简单大小写折叠映射进行大小写折叠再比较。简单映射总是映射为单一码点(如 ß 不会变为 ssSS)。但部分非Basic Latin字符可映射为Basic Latin内字符,如 ſ 会折叠为 s 会折叠为 k,因此如 /[a-z]/ui 可匹配这些字符。

HasEitherUnicodeFlag(rer) 为 false 时,映射基于 Unicode 默认大小写转换算法的 toUppercase,而不是 toCasefold,存在差异。例如 (U+2126)用 toUppercase 仍为自身,但 toCasefold 会变为 ω。所以 "\u2126" 能被 /[ω]/ui 匹配,不能被 /[ω]/i 匹配。非Basic Latin的字符不会映射到Basic Latin内字符。

22.2.2.7.4 UpdateModifiers (rer, add, remove)

抽象操作 UpdateModifiers 接收参数 rerRegExp Record)、add(字符串)、remove(字符串),返回一个 RegExp Record。调用时执行如下步骤:

  1. 断言addremove 没有公共元素。
  2. ignoreCase = rer.[[IgnoreCase]]
  3. multiline = rer.[[Multiline]]
  4. dotAll = rer.[[DotAll]]
  5. unicode = rer.[[Unicode]]
  6. unicodeSets = rer.[[UnicodeSets]]
  7. capturingGroupsCount = rer.[[CapturingGroupsCount]]
  8. 如果 remove 包含 "i",则令 ignoreCase = false
  9. 否则若 add 包含 "i",则令 ignoreCase = true
  10. 如果 remove 包含 "m",则令 multiline = false
  11. 否则若 add 包含 "m",则令 multiline = true
  12. 如果 remove 包含 "s",则令 dotAll = false
  13. 否则若 add 包含 "s",则令 dotAll = true
  14. 返回 RegExp Record { [[IgnoreCase]]: ignoreCase, [[Multiline]]: multiline, [[DotAll]]: dotAll, [[Unicode]]: unicode, [[UnicodeSets]]: unicodeSets, [[CapturingGroupsCount]]: capturingGroupsCount }。

22.2.2.8 运行时语义:CompileCharacterClass

语法定向操作 CompileCharacterClass 接收参数 rerRegExp Record),返回含字段 [[CharSet]]CharSet)和 [[Invert]](布尔值)的 Record。在以下产生式中分段定义:

CharacterClass :: [ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 返回 Record { [[CharSet]]: A, [[Invert]]: false }。
CharacterClass :: [^ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 如果 rer.[[UnicodeSets]]true,则:
    1. 返回 Record { [[CharSet]]: CharacterComplement(rer, A), [[Invert]]: false }。
  3. 返回 Record { [[CharSet]]: A, [[Invert]]: true }。

22.2.2.9 运行时语义:CompileToCharSet

语法定向操作 CompileToCharSet 接收参数 rerRegExp Record),返回 CharSet

注 1

本节在 B.1.2.8 中有补充。

在以下产生式中分段定义:

ClassContents :: [empty]
  1. 返回空 CharSet
NonemptyClassRanges :: ClassAtom NonemptyClassRangesNoDash
  1. A = CompileToCharSet of ClassAtom,参数为 rer
  2. B = CompileToCharSet of NonemptyClassRangesNoDash,参数为 rer
  3. 返回 AB 的并集。
NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. A = CompileToCharSet of 第一个 ClassAtom,参数为 rer
  2. B = CompileToCharSet of 第二个 ClassAtom,参数为 rer
  3. C = CompileToCharSet of ClassContents,参数为 rer
  4. D = CharacterRange(A, B)。
  5. 返回 DC 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash NonemptyClassRangesNoDash
  1. A = CompileToCharSet of ClassAtomNoDash,参数为 rer
  2. B = CompileToCharSet of NonemptyClassRangesNoDash,参数为 rer
  3. 返回 AB 的并集。
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. A = CompileToCharSet of ClassAtomNoDash,参数为 rer
  2. B = CompileToCharSet of ClassAtom,参数为 rer
  3. C = CompileToCharSet of ClassContents,参数为 rer
  4. D = CharacterRange(A, B)。
  5. 返回 DC 的并集。
注 2

ClassContents 可扩展为单个 ClassAtom 或由两个 ClassAtom 用连字符分隔的区间。后者情况下,ClassContents 包含两个 ClassAtom(含)之间的所有字符;如其中任一不是单字符(如 \w),或左端大于右端,则为错误。

注 3

即使忽略大小写,区间两端字符的大小写在区间确定时依然重要。例如 /[E-F]/i 只匹配 E, F, e, f,而 /[E-f]/i 匹配 Basic Latin 字母及 [, \, ], ^, _, `

注 4

- 可被当作字面量或区间。若在 ClassContents 首尾、区间端点、或区间后,视为字面量。

ClassAtom :: -
  1. 返回仅包含字符 - U+002D (HYPHEN-MINUS) 的 CharSet
ClassAtomNoDash :: SourceCharacter 但不能是 \]-
  1. 返回仅包含 SourceCharacter 匹配字符的 CharSet
ClassEscape :: b - CharacterEscape
  1. cv 为本 ClassEscapeCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回仅包含字符 cCharSet
注 5

ClassAtom 可使用正则中允许的转义序列,除 \b\B 和反向引用外。类中 \b 表示退格符,\B 和反向引用会报错。在 ClassAtom 使用反向引用是错误的。

CharacterClassEscape :: d
  1. 返回包含字符 09 的十元素 CharSet
CharacterClassEscape :: D
  1. SCharacterClassEscape:: d 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: s
  1. 返回包含 WhiteSpaceLineTerminator 产生式右侧所有码点的 CharSet
CharacterClassEscape :: S
  1. SCharacterClassEscape:: s 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: w
  1. 返回 MaybeSimpleCaseFolding(rer, WordCharacters(rer))。
CharacterClassEscape :: W
  1. SCharacterClassEscape:: w 返回的 CharSet
  2. 返回 CharacterComplement(rer, S)。
CharacterClassEscape :: p{ UnicodePropertyValueExpression }
  1. 返回 CompileToCharSet of UnicodePropertyValueExpression,参数为 rer
CharacterClassEscape :: P{ UnicodePropertyValueExpression }
  1. SCompileToCharSet of UnicodePropertyValueExpression,参数为 rer
  2. 断言S 仅包含单一码点。
  3. 返回 CharacterComplement(rer, S)。
UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue
  1. pssource text matched by UnicodePropertyName
  2. pUnicodeMatchProperty(rer, ps)。
  3. 断言p表 69Property name and aliases” 列中列出的 Unicode 属性名或属性别名。
  4. vssource text matched by UnicodePropertyValue
  5. vUnicodeMatchPropertyValue(p, vs)。
  6. A 为包含所有在字符数据库定义中具有属性 p 且值为 v 的 Unicode 码点的 CharSet
  7. 返回 MaybeSimpleCaseFolding(rer, A)。
UnicodePropertyValueExpression :: LoneUnicodePropertyNameOrValue
  1. ssource text matched by LoneUnicodePropertyNameOrValue
  2. 如果 UnicodeMatchPropertyValue(General_Category, s) 是 PropertyValueAliases.txt 中 General_Category (gc) 属性的 Unicode 属性值或属性值别名,则:
    1. 返回包含所有字符数据库定义中属性 “General_Category” 值为 s 的 Unicode 码点的 CharSet
  3. pUnicodeMatchProperty(rer, s)。
  4. 断言p表 70 “Property name and aliases” 列中列出的二值 Unicode 属性或二值属性别名,或 表 71 “Property name” 列中列出的字符串的二值 Unicode 属性。
  5. A 为包含所有字符数据库定义中属性 p 值为 “True” 的 CharSetElements 的 CharSet
  6. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassUnion :: ClassSetRange ClassUnionopt
  1. ACompileToCharSet of ClassSetRange,参数为 rer
  2. 如果 ClassUnion 存在,则:
    1. BCompileToCharSet of ClassUnion,参数为 rer
    2. 返回 CharSets AB 的并集。
  3. 返回 A
ClassUnion :: ClassSetOperand ClassUnionopt
  1. ACompileToCharSet of ClassSetOperand,参数为 rer
  2. 如果 ClassUnion 存在,则:
    1. BCompileToCharSet of ClassUnion,参数为 rer
    2. 返回 CharSets AB 的并集。
  3. 返回 A
ClassIntersection :: ClassSetOperand && ClassSetOperand
  1. ACompileToCharSet of 第一个 ClassSetOperand,参数为 rer
  2. BCompileToCharSet of 第二个 ClassSetOperand,参数为 rer
  3. 返回 CharSets AB 的交集。
ClassIntersection :: ClassIntersection && ClassSetOperand
  1. ACompileToCharSet of ClassIntersection,参数为 rer
  2. BCompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回 CharSets AB 的交集。
ClassSubtraction :: ClassSetOperand -- ClassSetOperand
  1. A 为第一个 CompileToCharSet of ClassSetOperand,参数为 rer
  2. B 为第二个 CompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet
ClassSubtraction :: ClassSubtraction -- ClassSetOperand
  1. ACompileToCharSet of ClassSubtraction,参数为 rer
  2. BCompileToCharSet of ClassSetOperand,参数为 rer
  3. 返回包含所有属于 A 但不属于 B 的 CharSetElements 的 CharSet
ClassSetRange :: ClassSetCharacter - ClassSetCharacter
  1. A 为第一个 CompileToCharSet of ClassSetCharacter,参数为 rer
  2. B 为第二个 CompileToCharSet of ClassSetCharacter,参数为 rer
  3. 返回 MaybeSimpleCaseFolding(rer, CharacterRange(A, B))。
注 6

结果通常包含两个或更多区间。当 UnicodeSets 为 true 且 IgnoreCase 为 true 时,MaybeSimpleCaseFolding(rer, [Ā-č]) 只包含该区间中奇数码点。

ClassSetOperand :: ClassSetCharacter
  1. ACompileToCharSet of ClassSetCharacter,参数为 rer
  2. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassSetOperand :: ClassStringDisjunction
  1. ACompileToCharSet of ClassStringDisjunction,参数为 rer
  2. 返回 MaybeSimpleCaseFolding(rer, A)。
ClassSetOperand :: NestedClass
  1. 返回 CompileToCharSet of NestedClass,参数为 rer
NestedClass :: [ ClassContents ]
  1. 返回 CompileToCharSet of ClassContents,参数为 rer
NestedClass :: [^ ClassContents ]
  1. ACompileToCharSet of ClassContents,参数为 rer
  2. 返回 CharacterComplement(rer, A)。
NestedClass :: \ CharacterClassEscape
  1. 返回 CompileToCharSet of CharacterClassEscape,参数为 rer
ClassStringDisjunction :: \q{ ClassStringDisjunctionContents }
  1. 返回 CompileToCharSet of ClassStringDisjunctionContents,参数为 rer
ClassStringDisjunctionContents :: ClassString
  1. sCompileClassSetString of ClassString,参数为 rer
  2. 返回仅包含字符串 sCharSet
ClassStringDisjunctionContents :: ClassString | ClassStringDisjunctionContents
  1. sCompileClassSetString of ClassString,参数为 rer
  2. A 为仅包含字符串 sCharSet
  3. BCompileToCharSet of ClassStringDisjunctionContents,参数为 rer
  4. 返回 CharSets AB 的并集。
ClassSetCharacter :: SourceCharacter 但不能是 ClassSetSyntaxCharacter \ CharacterEscape \ ClassSetReservedPunctuator
  1. cv 为本 ClassSetCharacterCharacterValue
  2. c 为字符值为 cv 的字符。
  3. 返回仅包含字符 cCharSet
ClassSetCharacter :: \b
  1. 返回仅包含字符 U+0008 (BACKSPACE) 的 CharSet

22.2.2.9.1 CharacterRange (A, B)

抽象操作 CharacterRange 接收参数 ACharSet)和 BCharSet),返回 CharSet。调用时执行如下步骤:

  1. 断言AB 各自仅包含一个字符。
  2. aA 中的唯一字符。
  3. bB 中的唯一字符。
  4. i 为字符 a 的字符值。
  5. j 为字符 b 的字符值。
  6. 断言ij
  7. 返回包含所有字符值在 ij(含)区间的字符的 CharSet

22.2.2.9.2 HasEitherUnicodeFlag (rer)

抽象操作 HasEitherUnicodeFlag 接收参数 rerRegExp Record),返回布尔值。调用时执行如下步骤:

  1. 如果 rer.[[Unicode]]truerer.[[UnicodeSets]]true,则:
    1. 返回 true
  2. 返回 false

22.2.2.9.3 WordCharacters (rer)

抽象操作 WordCharacters 接收参数 rerRegExp Record),返回 CharSet。返回正则表达式中 \b\B\w\W 所认为的“单词字符”。调用时执行如下步骤:

  1. basicWordChars 为包含所有 ASCII 单词字符CharSet
  2. extraWordChars 为包含所有字符 cCharSet,其中 c 不在 basicWordChars 内,但 Canonicalize(rer, c) 在 basicWordChars 内。
  3. 断言:除非 HasEitherUnicodeFlag(rer) 为 truerer.[[IgnoreCase]]true,否则 extraWordChars 为空。
  4. 返回 basicWordCharsextraWordChars 的并集。

22.2.2.9.4 AllCharacters (rer)

抽象操作 AllCharacters 接收参数 rerRegExp Record),返回 CharSet。根据正则表达式标志返回“所有字符”的集合。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]truerer.[[IgnoreCase]]true
    1. 返回包含所有无 简单大小写折叠映射(即 scf(c)=c)的 Unicode 码点 cCharSet
  2. 否则若 HasEitherUnicodeFlag(rer) 为 true
    1. 返回包含所有码点值的 CharSet
  3. 否则:
    1. 返回包含所有码元值的 CharSet

22.2.2.9.5 MaybeSimpleCaseFolding (rer, A)

抽象操作 MaybeSimpleCaseFolding 接收参数 rerRegExp Record)、ACharSet),返回 CharSet。如果 rer.[[UnicodeSets]]falserer.[[IgnoreCase]]false,则返回 A。否则,使用 Unicode Character Database 中 简单大小写折叠scf(cp))的定义,对 A 的每个 CharSetElement 的每个码点字符做映射,并返回结果 CharSet。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]falserer.[[IgnoreCase]]false,返回 A
  2. B 为一个新的空 CharSet
  3. A 的每一个 CharSetElement s,执行:
    1. t 为空字符序列。
    2. s 中每一个码点 cp,执行:
      1. scf(cp) 附加到 t
    3. t 添加到 B
  4. 返回 B

22.2.2.9.6 CharacterComplement (rer, S)

抽象操作 CharacterComplement 接收参数 rerRegExp Record)、SCharSet),返回 CharSet。调用时执行如下步骤:

  1. A = AllCharacters(rer)。
  2. 返回包含所有属于 A 但不属于 S 的 CharSetElements 的 CharSet

22.2.2.9.7 UnicodeMatchProperty (rer, p)

抽象操作 UnicodeMatchProperty 接收参数 rerRegExp Record)、pECMAScript 源文本),返回 Unicode 属性名。调用时执行如下步骤:

  1. 如果 rer.[[UnicodeSets]]truep表 71 “Property name” 列中的 Unicode 属性名,则:
    1. 返回 Unicode 码点 p 组成的 List
  2. 断言p表 69、“Property name and aliases” 或 表 70 中的 Unicode 属性名或属性别名。
  3. c 为该行 “Canonical property name” 列中给出的 p 的规范属性名。
  4. 返回 Unicode 码点 c 组成的 List

实现必须支持 表 69表 70表 71 中列出的 Unicode 属性名和别名。为保证互操作性,实现不得支持其他属性名或别名。

注 1

例如,Script_Extensions属性名)和 scx(属性别名)有效,但 script_extensionsScx 无效。

注 2

这些属性集合是 UTS18 RL1.2 要求的超集。

注 3

这些表中的拼写(包括大小写)与 Unicode Character Database 文件 PropertyAliases.txt 保持一致。该文件中的拼写是 保证稳定的

表 69:非二值(非布尔型)Unicode 属性别名及其规范属性名
属性名 及别名 规范 属性名
General_Category General_Category
gc
Script Script
sc
Script_Extensions Script_Extensions
scx
表 70:二值(布尔型)Unicode 属性别名及其规范属性名
属性名 及别名 规范 属性名
ASCII ASCII
ASCII_Hex_Digit ASCII_Hex_Digit
AHex
Alphabetic Alphabetic
Alpha
Any Any
Assigned Assigned
Bidi_Control Bidi_Control
Bidi_C
Bidi_Mirrored Bidi_Mirrored
Bidi_M
Case_Ignorable Case_Ignorable
CI
Cased Cased
Changes_When_Casefolded Changes_When_Casefolded
CWCF
Changes_When_Casemapped Changes_When_Casemapped
CWCM
Changes_When_Lowercased Changes_When_Lowercased
CWL
Changes_When_NFKC_Casefolded Changes_When_NFKC_Casefolded
CWKCF
Changes_When_Titlecased Changes_When_Titlecased
CWT
Changes_When_Uppercased Changes_When_Uppercased
CWU
Dash Dash
Default_Ignorable_Code_Point Default_Ignorable_Code_Point
DI
Deprecated Deprecated
Dep
Diacritic Diacritic
Dia
Emoji Emoji
Emoji_Component Emoji_Component
EComp
Emoji_Modifier Emoji_Modifier
EMod
Emoji_Modifier_Base Emoji_Modifier_Base
EBase
Emoji_Presentation Emoji_Presentation
EPres
Extended_Pictographic Extended_Pictographic
ExtPict
Extender Extender
Ext
Grapheme_Base Grapheme_Base
Gr_Base
Grapheme_Extend Grapheme_Extend
Gr_Ext
Hex_Digit Hex_Digit
Hex
IDS_Binary_Operator IDS_Binary_Operator
IDSB
IDS_Trinary_Operator IDS_Trinary_Operator
IDST
ID_Continue ID_Continue
IDC
ID_Start ID_Start
IDS
Ideographic Ideographic
Ideo
Join_Control Join_Control
Join_C
Logical_Order_Exception Logical_Order_Exception
LOE
Lowercase Lowercase
Lower
Math Math
Noncharacter_Code_Point Noncharacter_Code_Point
NChar
Pattern_Syntax Pattern_Syntax
Pat_Syn
Pattern_White_Space Pattern_White_Space
Pat_WS
Quotation_Mark Quotation_Mark
QMark
Radical Radical
Regional_Indicator Regional_Indicator
RI
Sentence_Terminal Sentence_Terminal
STerm
Soft_Dotted Soft_Dotted
SD
Terminal_Punctuation Terminal_Punctuation
Term
Unified_Ideograph Unified_Ideograph
UIdeo
Uppercase Uppercase
Upper
Variation_Selector Variation_Selector
VS
White_Space White_Space
space
XID_Continue XID_Continue
XIDC
XID_Start XID_Start
XIDS
表 71:字符串的二值(布尔型)Unicode 属性
属性名
Basic_Emoji(基础表情符号)
Emoji_Keycap_Sequence(表情符号按键序列)
RGI_Emoji_Modifier_Sequence(RGI表情符号修饰符序列)
RGI_Emoji_Flag_Sequence(RGI表情符号旗帜序列)
RGI_Emoji_Tag_Sequence(RGI表情符号标签序列)
RGI_Emoji_ZWJ_Sequence(RGI表情符号ZWJ序列)
RGI_Emoji(RGI表情符号)

22.2.2.9.8 UnicodeMatchPropertyValue (p, v)

抽象操作 UnicodeMatchPropertyValue 接收参数 pECMAScript 源文本)和 vECMAScript 源文本),返回一个 Unicode 属性值。调用时执行如下步骤:

  1. 断言p表 69“规范属性名”列中列出的规范、无别名的 Unicode 属性名
  2. 断言vPropertyValueAliases.txt 中针对属性 p 列出的属性值或属性值别名。
  3. valuev 的规范属性值,其值为对应行“规范属性值”列中给出的内容。
  4. 返回 Unicode 码点 value 组成的 List

实现必须支持 表 69 中属性对应的 PropertyValueAliases.txt 文件中列出的 Unicode 属性值和属性值别名。为保证互操作性,实现不得支持其他属性值或属性值别名。

注 1

例如,XpeoOld_Persian 是有效的 Script_Extensions 属性值,但 xpeoOld Persian 无效。

注 2

此算法不同于 UAX44 中列出的符号值匹配规则:不会忽略大小写、空白、U+002D(连字符)和 U+005F(下划线),并且不支持 Is 前缀。

22.2.2.10 运行时语义:CompileClassSetString

语法定向操作 CompileClassSetString 接收参数 rerRegExp Record),返回一个字符序列。该操作按以下产生式分段定义:

ClassString :: [empty]
  1. 返回空的字符序列。
ClassString :: NonEmptyClassString
  1. 返回 CompileClassSetString of NonEmptyClassString,参数为 rer
NonEmptyClassString :: ClassSetCharacter NonEmptyClassString opt
  1. csCompileToCharSet of ClassSetCharacter,参数为 rer
  2. s1cs 的唯一 CharSetElement 的字符序列。
  3. 如果 NonEmptyClassString 存在,则:
    1. s2CompileClassSetString of NonEmptyClassString,参数为 rer
    2. 返回 s1s2 的拼接。
  4. 返回 s1

22.2.3 正则表达式创建的抽象操作

22.2.3.1 RegExpCreate ( P, F )

抽象操作 RegExpCreate 接收参数 P(一个 ECMAScript 语言值)和 F(字符串或 undefined),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. obj 为 ! RegExpAlloc(%RegExp%)。
  2. 返回 ? RegExpInitialize(obj, P, F)。

22.2.3.2 RegExpAlloc ( newTarget )

抽象操作 RegExpAlloc 接收参数 newTarget构造函数),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. obj 为 ? OrdinaryCreateFromConstructor(newTarget, "%RegExp.prototype%", « [[OriginalSource]], [[OriginalFlags]], [[RegExpRecord]], [[RegExpMatcher]] »)。
  2. 执行 ! DefinePropertyOrThrow(obj, "lastIndex", PropertyDescriptor { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false })。
  3. 返回 obj

22.2.3.3 RegExpInitialize ( obj, pattern, flags )

抽象操作 RegExpInitialize 接收参数 obj(对象)、patternECMAScript 语言值)、flagsECMAScript 语言值),返回 包含对象的正常完成,或 抛出完成。调用时执行如下步骤:

  1. 如果 patternundefined,令 P 为空字符串。
  2. 否则,令 P 为 ? ToString(pattern)。
  3. 如果 flagsundefined,令 F 为空字符串。
  4. 否则,令 F 为 ? ToString(flags)。
  5. 如果 F 包含除 "d""g""i""m""s""u""v""y" 以外的任何代码单元,或 F 中有任何代码单元出现多次,则抛出 SyntaxError 异常。
  6. 如果 F 包含 "i",令 i = true;否则 i = false
  7. 如果 F 包含 "m",令 m = true;否则 m = false
  8. 如果 F 包含 "s",令 s = true;否则 s = false
  9. 如果 F 包含 "u",令 u = true;否则 u = false
  10. 如果 F 包含 "v",令 v = true;否则 v = false
  11. 如果 utruevtrue,则
    1. patternText = StringToCodePoints(P)。
  12. 否则:
    1. patternText 为将 P 的每个 16 位元素按 Unicode BMP 码点解释的结果。不会对这些元素做 UTF-16 解码。
  13. parseResult = ParsePattern(patternText, u, v)。
  14. 如果 parseResult 是一个非空的 List,且包含 SyntaxError 对象,则抛出 SyntaxError 异常。
  15. 断言parseResult 是一个 Pattern 解析节点
  16. 设置 obj.[[OriginalSource]] = P
  17. 设置 obj.[[OriginalFlags]] = F
  18. capturingGroupsCount = CountLeftCapturingParensWithin(parseResult)。
  19. rerRegExp Record { [[IgnoreCase]]: i, [[Multiline]]: m, [[DotAll]]: s, [[Unicode]]: u, [[UnicodeSets]]: v, [[CapturingGroupsCount]]: capturingGroupsCount }。
  20. 设置 obj.[[RegExpRecord]] = rer
  21. 设置 obj.[[RegExpMatcher]] = CompilePattern of parseResult,参数为 rer
  22. 执行 ? Set(obj, "lastIndex", +0𝔽, true)。
  23. 返回 obj

22.2.3.4 静态语义:ParsePattern (patternText, u, v)

抽象操作 ParsePattern 接收参数 patternText(Unicode码点序列)、u(布尔值)、v(布尔值),返回一个 解析节点,或一个非空的 List(元素为 SyntaxError 对象)。

本节在 B.1.2.9 中有补充说明。

调用时执行如下步骤:

  1. 如果 vtrueutrue
    1. parseResult 为包含一个或多个 SyntaxError 对象的 List
  2. 否则,如果 vtrue
    1. parseResult = ParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups])。
  3. 否则,如果 utrue
    1. parseResult = ParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  4. 否则:
    1. parseResult = ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups])。
  5. 返回 parseResult

22.2.4 RegExp 构造函数

RegExp 构造函数

  • %RegExp%
  • 全局对象"RegExp" 属性的初始值。
  • 作为 构造函数调用时,会创建并初始化一个新的 RegExp 对象。
  • 当作普通函数而非 构造函数调用时,返回一个新的 RegExp 对象,或者如果唯一参数本身就是 RegExp 对象,则返回该参数本身。
  • 可以作为类定义的 extends 子句的值。子类 构造函数 如果要继承指定的 RegExp 行为,必须包含对 RegExp 构造函数super 调用,以便用必要的内部插槽来创建并初始化子类实例。

22.2.4.1 RegExp ( pattern, flags )

该函数被调用时执行以下步骤:

  1. patternIsRegExp 为 ? IsRegExp(pattern)。
  2. 如果 NewTarget 是 undefined,则
    1. newTarget活动函数对象
    2. 如果 patternIsRegExptrueflagsundefined,则
      1. patternConstructor 为 ? Get(pattern, "constructor")。
      2. 如果 SameValue(newTarget, patternConstructor) 为 true,返回 pattern
  3. 否则,
    1. newTarget 为 NewTarget。
  4. 如果 pattern 是一个对象pattern[[RegExpMatcher]] 内部插槽,则
    1. Ppattern.[[OriginalSource]]
    2. 如果 flagsundefined,令 Fpattern.[[OriginalFlags]]
    3. 否则,令 Fflags
  5. 否则如果 patternIsRegExptrue,则
    1. P 为 ? Get(pattern, "source")。
    2. 如果 flagsundefined,则
      1. F 为 ? Get(pattern, "flags")。
    3. 否则,
      1. Fflags
  6. 否则,
    1. Ppattern
    2. Fflags
  7. O 为 ? RegExpAlloc(newTarget)。
  8. 返回 ? RegExpInitialize(O, P, F)。

如果 pattern 是通过 StringLiteral 传递的,会在该字符串被本函数处理前进行常规的转义序列替换。如果 pattern 必须包含一个转义序列以便被本函数识别,则必须在 StringLiteral 内对所有 U+005C(反斜杠)码点进行转义,以防止它们在形成 StringLiteral 内容时被移除。

22.2.5 RegExp 构造函数的属性

RegExp 构造函数

22.2.5.1 RegExp.escape ( S )

该函数返回 S 的一个副本,其中正则表达式模式中可能具有特殊含义的字符都被替换为等价的转义序列。

调用时执行以下步骤:

  1. 如果 S 不是字符串,抛出 TypeError 异常。
  2. escaped 为空字符串。
  3. cpListStringToCodePoints(S)。
  4. 对于 cpList 中的每个码点 cp,执行
    1. 如果 escaped 为空字符串,且 cp 匹配 十进制数字ASCII 字母, 则
      1. 注:转义首位数字可保证输出对应的模式文本在 \0 字符转义或 十进制转义(如 \1)后仍能匹配 S,不会被解释为前一转义序列的扩展。首位 ASCII 字母的转义同理,适用于 \c 后的情况。
      2. numericValuecp 的数值。
      3. hexNumber::toString(𝔽(numericValue), 16)。
      4. 断言hex 长度为 2。
      5. 设置 escaped 为字符串拼接 0x005C(反斜杠)、"x" 及 hex
    2. 否则,
      1. 设置 escapedescapedEncodeForRegExpEscape(cp) 的字符串拼接。
  5. 返回 escaped

虽然名字相似,EscapeRegExpPatternRegExp.escape 并不执行类似操作。前者用于将模式转义为字符串表示,后者用于将字符串转义为模式内部使用。

22.2.5.1.1 EncodeForRegExpEscape ( cp )

抽象操作 EncodeForRegExpEscape 接收参数 cp(码点),返回一个字符串。返回值即为匹配 cp 的模式 Pattern。如 cp 为空白字符或 ASCII 标点,则返回转义序列。否则,返回 cp 本身的字符串表示。调用时执行如下步骤:

  1. 如果 cp 匹配 SyntaxCharacter 或等于 U+002F(/),则
    1. 返回 0x005C(反斜杠)与 UTF16EncodeCodePoint(cp) 的字符串拼接。
  2. 否则,如果 cp表 67 的“Code Point”列中,则
    1. 返回 0x005C(反斜杠)与该行“ControlEscape”列字符串的字符串拼接。
  3. otherPunctuators 为字符串 ",-=<>#&!%:;@~'`" 与 0x0022(引号)。
  4. toEscapeStringToCodePoints(otherPunctuators)。
  5. 如果 toEscape 包含 cp,或 cp 匹配 WhiteSpaceLineTerminator,或 cp前导代理项尾随代理项数值相同,则
    1. cpNumcp 的数值。
    2. 如果 cpNum ≤ 0xFF,则
      1. hexNumber::toString(𝔽(cpNum), 16)。
      2. 返回 0x005C(反斜杠)、"x" 及 StringPad(hex, 2, "0", start) 的字符串拼接。
    3. escaped 为空字符串。
    4. codeUnitsUTF16EncodeCodePoint(cp)。
    5. 对于 codeUnits 中每个 code unit cu,执行
      1. 设置 escapedescapedUnicodeEscape(cu) 的字符串拼接。
    6. 返回 escaped
  6. 返回 UTF16EncodeCodePoint(cp)。

22.2.5.2 RegExp.prototype

RegExp.prototype 的初始值为 RegExp 原型对象

该属性具有属性:{ [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.5.3 get RegExp [ %Symbol.species% ]

RegExp[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数调用时执行如下步骤:

  1. 返回 this 值。

此函数的 "name" 属性值为 "get [Symbol.species]"

RegExp 原型方法通常使用其 this 值的 构造函数 来创建派生对象。但子类 构造函数 可以通过重定义其 %Symbol.species% 属性来覆盖此默认行为。

22.2.6 RegExp 原型对象的属性

RegExp 原型对象

  • %RegExp.prototype%
  • 是一个 普通对象
  • 不是 RegExp 实例,不具有 [[RegExpMatcher]] 内部插槽,也没有 RegExp 实例对象的其他内部插槽。
  • 拥有 [[Prototype]] 内部插槽,其值为 %Object.prototype%

RegExp 原型对象自身没有 "valueOf" 属性,但它从 Object 原型对象 继承了 "valueOf" 属性。

22.2.6.1 RegExp.prototype.constructor

RegExp.prototype.constructor 的初始值为 %RegExp%

22.2.6.2 RegExp.prototype.exec ( string )

该方法在 string 中搜索正则表达式的匹配项,并返回包含匹配结果的数组,若 string 不匹配则返回 null

调用时执行如下步骤:

  1. Rthis 值。
  2. 执行 ? RequireInternalSlot(R, [[RegExpMatcher]])。
  3. S 为 ? ToString(string)。
  4. 返回 ? RegExpBuiltinExec(R, S)。

22.2.6.3 get RegExp.prototype.dotAll

RegExp.prototype.dotAll 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0073(小写字母 s)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.4 get RegExp.prototype.flags

RegExp.prototype.flags 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. codeUnits 为一个新的空 List
  4. hasIndicesToBoolean(? Get(R, "hasIndices"))。
  5. 如果 hasIndicestrue,将码元 0x0064(小写字母 d)添加到 codeUnits
  6. globalToBoolean(? Get(R, "global"))。
  7. 如果 globaltrue,将码元 0x0067(g)添加到 codeUnits
  8. ignoreCaseToBoolean(? Get(R, "ignoreCase"))。
  9. 如果 ignoreCasetrue,将码元 0x0069(i)添加到 codeUnits
  10. multilineToBoolean(? Get(R, "multiline"))。
  11. 如果 multilinetrue,将码元 0x006D(m)添加到 codeUnits
  12. dotAllToBoolean(? Get(R, "dotAll"))。
  13. 如果 dotAlltrue,将码元 0x0073(s)添加到 codeUnits
  14. unicodeToBoolean(? Get(R, "unicode"))。
  15. 如果 unicodetrue,将码元 0x0075(u)添加到 codeUnits
  16. unicodeSetsToBoolean(? Get(R, "unicodeSets"))。
  17. 如果 unicodeSetstrue,将码元 0x0076(v)添加到 codeUnits
  18. stickyToBoolean(? Get(R, "sticky"))。
  19. 如果 stickytrue,将码元 0x0079(y)添加到 codeUnits
  20. 返回由 List codeUnits 组成的字符串;若 codeUnits 为空,则返回空字符串。

22.2.6.4.1 RegExpHasFlag ( R, codeUnit )

抽象操作 RegExpHasFlag 接收参数 RECMAScript 语言值)和 codeUnit(码元),返回一个 包含布尔值或 undefined 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. 如果 R 不是对象,抛出 TypeError 异常。
  2. 如果 R 没有 [[OriginalFlags]] 内部插槽,则
    1. 如果 SameValue(R, %RegExp.prototype%) 为 true,返回 undefined
    2. 否则,抛出 TypeError 异常。
  3. flagsR.[[OriginalFlags]]
  4. 如果 flags 包含 codeUnit,返回 true
  5. 返回 false

22.2.6.5 get RegExp.prototype.global

RegExp.prototype.global 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0067(g)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.6 get RegExp.prototype.hasIndices

RegExp.prototype.hasIndices 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0064(d)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.7 get RegExp.prototype.ignoreCase

RegExp.prototype.ignoreCase 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0069(i)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.8 RegExp.prototype [ %Symbol.match% ] ( string )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. flags 为 ? ToString(? Get(rx, "flags"))。
  5. 如果 flags 不包含 "g",则
    1. 返回 ? RegExpExec(rx, S)。
  6. 否则,
    1. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue。否则,令 fullUnicodefalse
    2. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
    3. A 为 ! ArrayCreate(0)。
    4. n 为 0。
    5. 重复,
      1. result 为 ? RegExpExec(rx, S)。
      2. 如果 resultnull,则
        1. 如果 n = 0,返回 null
        2. 返回 A
      3. 否则,
        1. matchStr 为 ? ToString(? Get(result, "0"))。
        2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), matchStr)。
        3. 如果 matchStr 是空字符串,则
          1. thisIndex(? ToLength(? Get(rx, "lastIndex")))。
          2. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
          3. 执行 ? Set(rx, "lastIndex", 𝔽(nextIndex), true)。
        4. 设置 nn + 1。

该方法的 "name" 属性值为 "[Symbol.match]"

%Symbol.match% 属性被 IsRegExp 抽象操作用于识别具有正则表达式基本行为的对象。如果缺少 %Symbol.match% 属性,或该属性的值经布尔转换不是 true,则表明该对象不应被当作正则表达式对象使用。

22.2.6.9 RegExp.prototype [ %Symbol.matchAll% ] ( string )

该方法调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. C 为 ? SpeciesConstructor(R, %RegExp%)。
  5. flags 为 ? ToString(? Get(R, "flags"))。
  6. matcher 为 ? Construct(C, « R, flags »)。
  7. lastIndex 为 ? ToLength(? Get(R, "lastIndex"))。
  8. 执行 ? Set(matcher, "lastIndex", lastIndex, true)。
  9. 如果 flags 包含 "g",令 globaltrue
  10. 否则,令 globalfalse
  11. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue
  12. 否则,令 fullUnicodefalse
  13. 返回 CreateRegExpStringIterator(matcher, S, global, fullUnicode)。

该方法的 "name" 属性值为 "[Symbol.matchAll]"

22.2.6.10 get RegExp.prototype.multiline

RegExp.prototype.multiline 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x006D(m)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.11 RegExp.prototype [ %Symbol.replace% ] ( string, replaceValue )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. lengthSS 的长度。
  5. functionalReplaceIsCallable(replaceValue)。
  6. 如果 functionalReplacefalse,则
    1. 设置 replaceValue 为 ? ToString(replaceValue)。
  7. flags 为 ? ToString(? Get(rx, "flags"))。
  8. 如果 flags 包含 "g",令 globaltrue;否则 globalfalse
  9. 如果 globaltrue,则
    1. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
  10. results 为一个新的空 List
  11. donefalse
  12. 重复,直到 donefalse
    1. result 为 ? RegExpExec(rx, S)。
    2. 如果 resultnull,则
      1. 设置 donetrue
    3. 否则,
      1. result 添加到 results
      2. 如果 globalfalse,则
        1. 设置 donetrue
      3. 否则,
        1. matchStr 为 ? ToString(? Get(result, "0"))。
        2. 如果 matchStr 是空字符串,则
          1. thisIndex(? ToLength(? Get(rx, "lastIndex")))。
          2. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则 fullUnicodefalse
          3. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
          4. 执行 ? Set(rx, "lastIndex", 𝔽(nextIndex), true)。
  13. accumulatedResult 为空字符串。
  14. nextSourcePosition 为 0。
  15. 对于 results 中的每个元素 result,执行
    1. resultLength 为 ? LengthOfArrayLike(result)。
    2. nCapturesmax(resultLength - 1, 0)。
    3. matched 为 ? ToString(? Get(result, "0"))。
    4. matchLengthmatched 的长度。
    5. position 为 ? ToIntegerOrInfinity(? Get(result, "index"))。
    6. position 限制在 0 到 lengthS 之间。
    7. captures 为一个新的空 List
    8. n 为 1。
    9. 重复,直到 nnCaptures
      1. capN 为 ? Get(result, ! ToString(𝔽(n)))。
      2. 如果 capN 不为 undefined,则
        1. 设置 capN 为 ? ToString(capN)。
      3. capN 添加到 captures
      4. 注:当 n = 1 时,上一步将第一个元素放入 captures(索引 0)。更一般地,第 n 个捕获组(第 n 对括号捕获的字符)在 captures[n - 1]。
      5. 设置 nn + 1。
    10. namedCaptures 为 ? Get(result, "groups")。
    11. 如果 functionalReplacetrue,则
      1. replacerArgs 为 « matched »、captures 和 « 𝔽(position), S » 的列表拼接。
      2. 如果 namedCaptures 不为 undefined,则
        1. namedCaptures 添加到 replacerArgs
      3. replacementValue 为 ? Call(replaceValue, undefined, replacerArgs)。
      4. replacementString 为 ? ToString(replacementValue)。
    12. 否则,
      1. 如果 namedCaptures 不为 undefined,则
        1. 设置 namedCaptures 为 ? ToObject(namedCaptures)。
      2. replacementString 为 ? GetSubstitution(matched, S, position, captures, namedCaptures, replaceValue)。
    13. 如果 positionnextSourcePosition,则
      1. 注:position 通常不会倒退。如果发生,说明是行为异常的 RegExp 子类或通过副作用改变了 global 标志或 rx 的其它特性,此时对应替换会被忽略。
      2. 设置 accumulatedResultaccumulatedResultSnextSourcePositionposition 子串、和 replacementString 的字符串拼接。
      3. 设置 nextSourcePositionposition + matchLength
  16. 如果 nextSourcePositionlengthS,返回 accumulatedResult
  17. 返回 accumulatedResultSnextSourcePosition 开始的子串的字符串拼接。

该方法的 "name" 属性值为 "[Symbol.replace]"

22.2.6.12 RegExp.prototype [ %Symbol.search% ] ( string )

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. previousLastIndex 为 ? Get(rx, "lastIndex")。
  5. 如果 previousLastIndex 不为 +0𝔽,则
    1. 执行 ? Set(rx, "lastIndex", +0𝔽, true)。
  6. result 为 ? RegExpExec(rx, S)。
  7. currentLastIndex 为 ? Get(rx, "lastIndex")。
  8. 如果 SameValue(currentLastIndex, previousLastIndex) 为 false,则
    1. 执行 ? Set(rx, "lastIndex", previousLastIndex, true)。
  9. 如果 resultnull,返回 -1𝔽
  10. 返回 ? Get(result, "index")。

该方法的 "name" 属性值为 "[Symbol.search]"

本 RegExp 对象的 "lastIndex""global" 属性在执行搜索时会被忽略,并且 "lastIndex" 属性保持不变。

22.2.6.13 get RegExp.prototype.source

RegExp.prototype.source 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. 如果 R 没有 [[OriginalSource]] 内部插槽,则
    1. 如果 SameValue(R, %RegExp.prototype%) 为 true,返回 "(?:)"
    2. 否则,抛出 TypeError 异常。
  4. 断言R 拥有 [[OriginalFlags]] 内部插槽。
  5. srcR.[[OriginalSource]]
  6. flagsR.[[OriginalFlags]]
  7. 返回 EscapeRegExpPattern(src, flags)。

22.2.6.13.1 EscapeRegExpPattern ( P, F )

抽象操作 EscapeRegExpPattern 接收参数 P(字符串)和 F(字符串),返回一个字符串。调用时执行如下步骤:

  1. 如果 F 包含 "v",则
    1. patternSymbolPattern[+UnicodeMode, +UnicodeSetsMode]
  2. 否则如果 F 包含 "u",则
    1. patternSymbolPattern[+UnicodeMode, ~UnicodeSetsMode]
  3. 否则:
    1. patternSymbolPattern[~UnicodeMode, ~UnicodeSetsMode]
  4. S 为形式为 patternSymbol 的字符串,其内容等价于将 P 按 UTF-16 编码的 Unicode 码点解释后得到的模式,并对部分码点按下述方式转义。S 可能与 P 相同,也可能不同;但对 S 作为 patternSymbol 求值所得的 抽象闭包 必须与构造对象的 [[RegExpMatcher]] 内部插槽给出的 抽象闭包 行为一致。对同一 PF 多次调用本操作,结果必须一致。
  5. pattern 中的 / 及所有 LineTerminator 码点须在 S 中转义,以确保 字符串拼接 "/"S"/"F 可作为 RegularExpressionLiteral 被解析,并与构造的正则表达式行为一致。如 P"/",则 S 可为 "\/""\u002F",但不能为 "/",否则 /// 后接 F 会被解析为 单行注释 而不是 正则表达式字面量。若 P 为空字符串,则 S 可为 "(?:)"
  6. 返回 S

尽管名字类似,RegExp.escape 与 EscapeRegExpPattern 并不执行类似操作。前者用于将字符串转义为可在模式中使用的内容,后者用于将模式转义为可作为字符串表示。

22.2.6.14 RegExp.prototype [ %Symbol.split% ] ( string, limit )

注 1

该方法返回一个数组,数组中存储了将 string 转换为字符串后的子串。这些子串是通过从左到右搜索 this 值正则表达式的匹配项确定的;这些匹配项不属于返回数组中的任何字符串,而是将字符串拆分开。

this 值可以是空正则表达式,也可以是能够匹配空字符串的正则表达式。在这种情况下,正则表达式不会匹配输入字符串开头或结尾的空子串,也不会匹配前一个分隔符匹配末尾的空子串。(例如,如果正则表达式匹配空字符串,则字符串会被拆分为单个码元元素;结果数组长度等于字符串长度,每个子串只包含一个码元。)某个索引处只考虑第一次匹配,即使回溯能得到非空子串匹配也不会采纳。(例如,/a*?/[Symbol.split]("ab") 的结果是 ["a", "b"],而 /a*/[Symbol.split]("ab") 的结果是 ["","b"]。)

如果 string 是(或转换为)空字符串,结果取决于正则表达式是否能匹配空字符串。如果能,结果数组无元素;否则,结果数组含一个元素,即空字符串。

如果正则表达式含有捕获括号,则每次 separator 匹配时,括号捕获的结果(包括 undefined)会被拼接进输出数组。例如,

/<(\/)?([^<>]+)>/[Symbol.split]("A<B>bold</B>and<CODE>coded</CODE>")

结果为数组

["A", undefined, "B", "bold", "/", "B", "and", undefined, "CODE", "coded", "/", "CODE", ""]

如果 limit 不为 undefined,则输出数组会被截断为不多于 limit 个元素。

该方法调用时执行如下步骤:

  1. rxthis 值。
  2. 如果 rx 不是对象,抛出 TypeError 异常。
  3. S 为 ? ToString(string)。
  4. C 为 ? SpeciesConstructor(rx, %RegExp%)。
  5. flags 为 ? ToString(? Get(rx, "flags"))。
  6. 如果 flags 包含 "u"flags 包含 "v",令 unicodeMatchingtrue
  7. 否则,令 unicodeMatchingfalse
  8. 如果 flags 包含 "y",令 newFlagsflags
  9. 否则,令 newFlagsflags"y" 的字符串拼接。
  10. splitter 为 ? Construct(C, « rx, newFlags »)。
  11. A 为 ! ArrayCreate(0)。
  12. lengthA 为 0。
  13. 如果 limitundefined,令 lim 为 232 - 1;否则,令 lim(? ToUint32(limit))。
  14. 如果 lim = 0,返回 A
  15. 如果 S 是空字符串,则
    1. z 为 ? RegExpExec(splitter, S)。
    2. 如果 z 不为 null,返回 A
    3. 执行 ! CreateDataPropertyOrThrow(A, "0", S)。
    4. 返回 A
  16. sizeS 的长度。
  17. p 为 0。
  18. qp
  19. 重复,直到 q < size
    1. 执行 ? Set(splitter, "lastIndex", 𝔽(q), true)。
    2. z 为 ? RegExpExec(splitter, S)。
    3. 如果 znull,则
      1. 设置 qAdvanceStringIndex(S, q, unicodeMatching)。
    4. 否则,
      1. e(? ToLength(? Get(splitter, "lastIndex")))。
      2. e 限制为不大于 size
      3. 如果 e = p,则
        1. 设置 qAdvanceStringIndex(S, q, unicodeMatching)。
      4. 否则,
        1. Tsubstring of Spq
        2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T)。
        3. 设置 lengthAlengthA + 1。
        4. 如果 lengthA = lim,返回 A
        5. 设置 pe
        6. numberOfCaptures 为 ? LengthOfArrayLike(z)。
        7. numberOfCaptures 限制为 numberOfCaptures - 1 与 0 之间的最大值。
        8. i 为 1。
        9. 重复,直到 inumberOfCaptures
          1. nextCapture 为 ? Get(z, ! ToString(𝔽(i)))。
          2. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), nextCapture)。
          3. 设置 ii + 1。
          4. 设置 lengthAlengthA + 1。
          5. 如果 lengthA = lim,返回 A
        10. 设置 qp
  20. Tsubstring of Spsize
  21. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(lengthA)), T)。
  22. 返回 A

该方法的 "name" 属性值为 "[Symbol.split]"

注 2

该方法会忽略本 RegExp 对象的 "global""sticky" 属性值。

22.2.6.15 get RegExp.prototype.sticky

RegExp.prototype.sticky 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0079(y)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.16 RegExp.prototype.test ( S )

该方法调用时执行如下步骤:

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. string 为 ? ToString(S)。
  4. match 为 ? RegExpExec(R, string)。
  5. 如果 match 不为 null,返回 true;否则返回 false

22.2.6.17 RegExp.prototype.toString ( )

  1. Rthis 值。
  2. 如果 R 不是对象,抛出 TypeError 异常。
  3. pattern 为 ? ToString(? Get(R, "source"))。
  4. flags 为 ? ToString(? Get(R, "flags"))。
  5. result字符串拼接 "/"pattern"/"flags
  6. 返回 result

返回的字符串具有 RegularExpressionLiteral 的形式,求值后是另一个行为与本对象一致的 RegExp 对象。

22.2.6.18 get RegExp.prototype.unicode

RegExp.prototype.unicode 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0075(u)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.6.19 get RegExp.prototype.unicodeSets

RegExp.prototype.unicodeSets 是一个 访问器属性,其 set 访问器函数为 undefined。get 访问器函数调用时执行如下步骤:

  1. Rthis 值。
  2. cu 为码元 0x0076(v)。
  3. 返回 ? RegExpHasFlag(R, cu)。

22.2.7 正则匹配的抽象操作

22.2.7.1 RegExpExec ( R, S )

抽象操作 RegExpExec 接收参数 R(对象)和 S(字符串),返回 包含对象或 null 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. exec 为 ? Get(R, "exec")。
  2. 如果 IsCallable(exec) 为 true,则
    1. result 为 ? Call(exec, R, « S »)。
    2. 如果 result 不是对象result 不是 null,抛出 TypeError 异常。
    3. 返回 result
  3. 执行 ? RequireInternalSlot(R, [[RegExpMatcher]])。
  4. 返回 ? RegExpBuiltinExec(R, S)。

如果未找到可调用的 "exec" 属性,本算法会退回内建正则匹配算法。这为针对早期版本编写的代码提供了兼容行为,此前大多数使用正则表达式的内建算法不会动态查找 "exec" 属性。

22.2.7.2 RegExpBuiltinExec ( R, S )

抽象操作 RegExpBuiltinExec 接收参数 R(初始化后的 RegExp 实例)和 S(字符串),返回 包含一个 数组异类对象null 的正常完成,或 抛出完成。调用时执行如下步骤:

  1. lengthS 的长度。
  2. lastIndex(? ToLength(? Get(R, "lastIndex")))。
  3. flagsR.[[OriginalFlags]]
  4. 如果 flags 包含 "g",令 globaltrue;否则为 false
  5. 如果 flags 包含 "y",令 stickytrue;否则为 false
  6. 如果 flags 包含 "d",令 hasIndicestrue;否则为 false
  7. 如果 globalfalsestickyfalse,将 lastIndex 设为 0。
  8. matcherR.[[RegExpMatcher]]
  9. 如果 flags 包含 "u"flags 包含 "v",令 fullUnicodetrue;否则为 false
  10. matchSucceededfalse
  11. 如果 fullUnicodetrue,令 inputStringToCodePoints(S);否则,令 input 为包含 S 各码元的 List
  12. 注:input 的每个元素都被视为一个字符。
  13. 重复,直到 matchSucceededfalse
    1. 如果 lastIndex > length,则
      1. 如果 globalstickytrue,则
        1. 执行 ? Set(R, "lastIndex", +0𝔽, true)。
      2. 返回 null
    2. inputIndexS 索引 lastIndex 处对应 input 的下标。
    3. rmatcher(input, inputIndex)。
    4. 如果 rfailure,则
      1. 如果 stickytrue,则
        1. 执行 ? Set(R, "lastIndex", +0𝔽, true)。
        2. 返回 null
      2. lastIndex 设为 AdvanceStringIndex(S, lastIndex, fullUnicode)。
    5. 否则,
      1. 断言rMatchState
      2. 设置 matchSucceededtrue
  14. er.[[EndIndex]]
  15. 如果 fullUnicodetrue,则将 e 设为 GetStringIndex(S, e)。
  16. 如果 globalstickytrue,则
    1. 执行 ? Set(R, "lastIndex", 𝔽(e), true)。
  17. nr.[[Captures]] 的元素数。
  18. 断言n = R.[[RegExpRecord]].[[CapturingGroupsCount]]
  19. 断言n < 232 - 1。
  20. A 为 ! ArrayCreate(n + 1)。
  21. 断言A"length" 数学值为 n + 1。
  22. 执行 ! CreateDataPropertyOrThrow(A, "index", 𝔽(lastIndex))。
  23. 执行 ! CreateDataPropertyOrThrow(A, "input", S)。
  24. matchMatch Record { [[StartIndex]]: lastIndex, [[EndIndex]]: e }。
  25. indices 为一个新的空 List
  26. groupNames 为一个新的空 List
  27. match 添加到 indices
  28. matchedSubstrGetMatchString(S, match)。
  29. 执行 ! CreateDataPropertyOrThrow(A, "0", matchedSubstr)。
  30. 如果 R 包含 GroupName
    1. groupsOrdinaryObjectCreate(null)。
    2. hasGroupstrue
  31. 否则,
    1. groupsundefined
    2. hasGroupsfalse
  32. 执行 ! CreateDataPropertyOrThrow(A, "groups", groups)。
  33. matchedGroupNames 为一个新的空 List
  34. 对于所有 1 ≤ in 的整数 i,升序执行
    1. captureIr.[[Captures]] 的第 i 个元素。
    2. 如果 captureIundefined
      1. capturedValueundefined
      2. undefined 添加到 indices
    3. 否则,
      1. captureStartcaptureI.[[StartIndex]]
      2. captureEndcaptureI.[[EndIndex]]
      3. 如果 fullUnicodetrue
        1. 设置 captureStartGetStringIndex(S, captureStart)。
        2. 设置 captureEndGetStringIndex(S, captureEnd)。
      4. captureMatch Record { [[StartIndex]]: captureStart, [[EndIndex]]: captureEnd }。
      5. capturedValueGetMatchString(S, capture)。
      6. capture 添加到 indices
    4. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(i)), capturedValue)。
    5. 如果 R 的第 i 个捕获带有 GroupName
      1. s 为该 GroupNameCapturingGroupName
      2. 如果 matchedGroupNames 包含 s
        1. 断言capturedValueundefined
        2. undefined 添加到 groupNames
      3. 否则,
        1. 如果 capturedValue 不为 undefined,将 s 添加到 matchedGroupNames
        2. 注:如有多个同名分组,groups 可能已有属性 s。但因 groups 是普通对象,其属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, s, capturedValue)。
        4. s 添加到 groupNames
    6. 否则,
      1. undefined 添加到 groupNames
  35. 如果 hasIndicestrue
    1. indicesArrayMakeMatchIndicesIndexPairArray(S, indices, groupNames, hasGroups)。
    2. 执行 ! CreateDataPropertyOrThrow(A, "indices", indicesArray)。
  36. 返回 A

22.2.7.3 AdvanceStringIndex ( S, index, unicode )

抽象操作 AdvanceStringIndex 接收参数 S(字符串)、index(非负整数)、unicode(布尔值),返回一个整数。调用时执行如下步骤:

  1. 断言index ≤ 253 - 1。
  2. 如果 unicodefalse,返回 index + 1。
  3. lengthS 的长度。
  4. 如果 index + 1 ≥ length,返回 index + 1。
  5. cpCodePointAt(S, index)。
  6. 返回 index + cp.[[CodeUnitCount]]

22.2.7.4 GetStringIndex ( S, codePointIndex )

抽象操作 GetStringIndex 接收参数 S(字符串)和 codePointIndex(非负整数),返回一个非负整数。它将 S 作为 UTF-16 编码码点序列,根据 6.1.4,返回与码点索引 codePointIndex 对应的码元索引,若不存在则返回 S 的长度。调用时执行如下步骤:

  1. 如果 S 是空字符串,返回 0。
  2. lenS 的长度。
  3. codeUnitCount 为 0。
  4. codePointCount 为 0。
  5. 重复,直到 codeUnitCount < len
    1. 如果 codePointCount = codePointIndex,返回 codeUnitCount
    2. cpCodePointAt(S, codeUnitCount)。
    3. 设置 codeUnitCountcodeUnitCount + cp.[[CodeUnitCount]]
    4. 设置 codePointCountcodePointCount + 1。
  6. 返回 len

22.2.7.5 匹配记录(Match Records)

匹配记录(Match Record) 是一种 Record 值,用于封装正则匹配或捕获的起止索引。

匹配记录的字段列于 表 72

表 72:Match Record 字段
字段名 含义
[[StartIndex]] 非负 整数 匹配开始(包含)的字符串起始码元数。
[[EndIndex]] 一个 整数,且 ≥ [[StartIndex]] 匹配结束(不含)的字符串起始码元数。

22.2.7.6 GetMatchString ( S, match )

抽象操作 GetMatchString 接收参数 S(字符串)和 matchMatch Record),返回一个字符串。调用时执行如下步骤:

  1. 断言match.[[StartIndex]]match.[[EndIndex]]S 的长度。
  2. 返回 Smatch.[[StartIndex]]match.[[EndIndex]]子串

22.2.7.7 GetMatchIndexPair ( S, match )

抽象操作 GetMatchIndexPair 接收参数 S(字符串)和 matchMatch Record),返回一个数组。调用时执行如下步骤:

  1. 断言match.[[StartIndex]]match.[[EndIndex]]S 的长度。
  2. 返回 CreateArrayFromList𝔽(match.[[StartIndex]]), 𝔽(match.[[EndIndex]])»)。

22.2.7.8 MakeMatchIndicesIndexPairArray ( S, indices, groupNames, hasGroups )

抽象操作 MakeMatchIndicesIndexPairArray 接收参数 S(字符串)、indicesList,元素为 Match Recordsundefined)、groupNamesList,元素为字符串或 undefined)、hasGroups(布尔值),返回一个数组。调用时执行如下步骤:

  1. nindices 的元素数。
  2. 断言n < 232 - 1。
  3. 断言groupNamesn - 1 个元素。
  4. 注:groupNames 列表中的元素与 indices 列表自 indices[1] 起一一对应。
  5. A 为 ! ArrayCreate(n)。
  6. 如果 hasGroupstrue
    1. groupsOrdinaryObjectCreate(null)。
  7. 否则,
    1. groupsundefined
  8. 执行 ! CreateDataPropertyOrThrow(A, "groups", groups)。
  9. 对于 0 ≤ i < n 的每个整数 i,升序执行
    1. matchIndicesindices[i]。
    2. 如果 matchIndices 不为 undefined
      1. matchIndexPairGetMatchIndexPair(S, matchIndices)。
    3. 否则,
      1. matchIndexPairundefined
    4. 执行 ! CreateDataPropertyOrThrow(A, !ToString(𝔽(i)), matchIndexPair)。
    5. 如果 i > 0,
      1. sgroupNames[i - 1]。
      2. 如果 s 不为 undefined
        1. 断言groups 不为 undefined
        2. 注:如有多个同名分组,groups 可能已经有 s 属性。因 groups 是普通对象,属性均为可写数据属性,CreateDataPropertyOrThrow 调用必然成功。
        3. 执行 ! CreateDataPropertyOrThrow(groups, s, matchIndexPair)。
  10. 返回 A

22.2.8 RegExp 实例的属性

RegExp 实例是 普通对象,继承自 RegExp 原型对象。RegExp 实例具有内部插槽 [[OriginalSource]][[OriginalFlags]][[RegExpRecord]][[RegExpMatcher]][[RegExpMatcher]] 插槽的值是该正则对象 模式抽象闭包 表示。

在 ECMAScript 2015 之前,RegExp 实例被规范为拥有自身的数据属性 data properties "source""global""ignoreCase""multiline"。这些属性现在被规范为 RegExp.prototype访问器属性

RegExp 实例还具有以下属性:

22.2.8.1 lastIndex

"lastIndex" 属性的值指定下次匹配时从字符串的哪个索引开始。使用时会被强制转换为 整数类型 Number(参见 22.2.7.2)。该属性具有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

22.2.9 RegExp 字符串迭代器对象

RegExp 字符串迭代器是用于表示对某个特定字符串实例对象、针对某个特定 RegExp 实例对象进行迭代的对象。RegExp 字符串迭代器对象没有具名的 构造函数,而是通过调用某些 RegExp 实例对象的方法创建的。

22.2.9.1 CreateRegExpStringIterator ( R, S, global, fullUnicode )

抽象操作 CreateRegExpStringIterator 接收参数 R(对象)、S(字符串)、global(布尔值)、fullUnicode(布尔值),返回一个对象。调用时执行如下步骤:

  1. iteratorOrdinaryObjectCreate(%RegExpStringIteratorPrototype%, « [[IteratingRegExp]], [[IteratedString]], [[Global]], [[Unicode]], [[Done]] »)。
  2. 设置 iterator.[[IteratingRegExp]] = R
  3. 设置 iterator.[[IteratedString]] = S
  4. 设置 iterator.[[Global]] = global
  5. 设置 iterator.[[Unicode]] = fullUnicode
  6. 设置 iterator.[[Done]] = false
  7. 返回 iterator

22.2.9.2 %RegExpStringIteratorPrototype% 对象

%RegExpStringIteratorPrototype% 对象:

22.2.9.2.1 %RegExpStringIteratorPrototype%.next ( )

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. 如果 O 不具有 RegExp 字符串迭代器对象实例的所有内部插槽(见 22.2.9.3),抛出 TypeError 异常。
  4. 如果 O.[[Done]]true
    1. 返回 CreateIteratorResultObject(undefined, true)。
  5. R = O.[[IteratingRegExp]]
  6. S = O.[[IteratedString]]
  7. global = O.[[Global]]
  8. fullUnicode = O.[[Unicode]]
  9. match 为 ? RegExpExec(R, S)。
  10. 如果 matchnull
    1. 设置 O.[[Done]] = true
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 如果 globalfalse
    1. 设置 O.[[Done]] = true
    2. 返回 CreateIteratorResultObject(match, false)。
  12. matchStr 为 ? ToString(? Get(match, "0"))。
  13. 如果 matchStr 是空字符串,
    1. thisIndex(? ToLength(? Get(R, "lastIndex")))。
    2. nextIndexAdvanceStringIndex(S, thisIndex, fullUnicode)。
    3. 执行 ? Set(R, "lastIndex", 𝔽(nextIndex), true)。
  14. 返回 CreateIteratorResultObject(match, false)。

22.2.9.2.2 %RegExpStringIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值是字符串 "RegExp String Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

22.2.9.3 RegExp 字符串迭代器实例的属性

RegExp 字符串迭代器 实例是 普通对象,继承自 %RegExpStringIteratorPrototype% 内置对象。RegExp 字符串迭代器 实例初始时拥有 表 73 所列的内部插槽。

表 73:RegExp 字符串迭代器实例的内部插槽
内部插槽 类型 描述
[[IteratingRegExp]] 对象 用于迭代的正则表达式。IsRegExp([[IteratingRegExp]]) 初始为 true
[[IteratedString]] 字符串 被迭代的字符串值。
[[Global]] 布尔值 指示 [[IteratingRegExp]] 是否为全局。
[[Unicode]] 布尔值 指示 [[IteratingRegExp]] 是否为 Unicode 模式。
[[Done]] 布尔值 指示迭代是否已完成。

23 索引集合

23.1 数组对象

数组是特殊对象,对某类属性名进行了特殊处理。关于此特殊处理的定义,见10.4.2

23.1.1 Array 构造函数

Array 构造函数

  • %Array%
  • 全局对象"Array" 属性的初始值。
  • 作为构造函数调用时,会创建并初始化一个新的数组。
  • 作为普通函数而不是构造函数调用时,也会创建并初始化一个新的数组。因此,函数调用 Array(…) 等价于使用相同参数的对象创建表达式 new Array(…)
  • 是一个其行为根据参数数量和类型而异的函数。
  • 可用作类定义中 extends 子句的值。打算继承数组特殊行为的子类构造函数,必须包含对 Array 构造函数super 调用,以初始化作为数组特殊对象的子类实例。然而,大多数 Array.prototype 方法是泛型方法,不依赖于其 this 值为数组特殊对象

23.1.1.1 Array ( ...values )

当调用该函数时,执行以下步骤:

  1. 如果 NewTarget 为 undefined,则令 newTarget活动函数对象;否则令 newTarget 为 NewTarget。
  2. proto 为 ? GetPrototypeFromConstructor(newTarget, "%Array.prototype%")。
  3. numberOfArgsvalues 中元素的数量。
  4. 如果 numberOfArgs = 0,则
    1. 返回 ! ArrayCreate(0, proto)。
  5. 否则如果 numberOfArgs = 1,则
    1. lenvalues[0]。
    2. array 为 ! ArrayCreate(0, proto)。
    3. 如果 len 不是数字类型,则
      1. 执行 ! CreateDataPropertyOrThrow(array, "0", len)。
      2. intLen1𝔽
    4. 否则,
      1. intLen 为 ! ToUint32(len)。
      2. 如果 SameValueZero(intLen, len) 为 false,则抛出 RangeError 异常。
    5. 执行 ! Set(array, "length", intLen, true)。
    6. 返回 array
  6. 否则,
    1. 断言numberOfArgs ≥ 2。
    2. array 为 ? ArrayCreate(numberOfArgs, proto)。
    3. k 为 0。
    4. 重复,直到 k < numberOfArgs
      1. Pk 为 ! ToString(𝔽(k))。
      2. itemKvalues[k]。
      3. 执行 ! CreateDataPropertyOrThrow(array, Pk, itemK)。
      4. kk + 1。
    5. 断言array"length" 属性的数学值为 numberOfArgs
    6. 返回 array

23.1.2 Array 构造函数的属性

Array 构造函数

  • 具有一个名为 [[Prototype]] 的内部槽,其值为 %Function.prototype%
  • 具有一个值为 1𝔽"length" 属性。
  • 具有以下属性:

23.1.2.1 Array.from ( items [ , mapper [ , thisArg ] ] )

当调用该方法时,执行以下步骤:

  1. Cthis 值。
  2. 如果 mapperundefined,则
    1. mappingfalse
  3. 否则,
    1. 如果 IsCallable(mapper) 为 false,则抛出 TypeError 异常。
    2. mappingtrue
  4. usingIterator 为 ? GetMethod(items, %Symbol.iterator%)。
  5. 如果 usingIterator 不为 undefined,则
    1. 如果 IsConstructor(C) 为 true,则
      1. A 为 ? Construct(C)。
    2. 否则,
      1. A 为 ! ArrayCreate(0)。
    3. iteratorRecord 为 ? GetIteratorFromMethod(items, usingIterator)。
    4. k 为 0。
    5. 重复,
      1. 如果 k ≥ 253 - 1,则
        1. errorThrowCompletion(新建的 TypeError 对象)。
        2. 返回 ? IteratorClose(iteratorRecord, error)。
      2. Pk 为 ! ToString(𝔽(k))。
      3. next 为 ? IteratorStepValue(iteratorRecord)。
      4. 如果 nextdone,则
        1. 执行 ? Set(A, "length", 𝔽(k), true)。
        2. 返回 A
      5. 如果 mappingtrue,则
        1. mappedValueCompletion(Call(mapper, thisArg, « next, 𝔽(k) »))。
        2. IfAbruptCloseIterator(mappedValue, iteratorRecord)。
      6. 否则,
        1. mappedValuenext
      7. defineStatusCompletion(CreateDataPropertyOrThrow(A, Pk, mappedValue))。
      8. IfAbruptCloseIterator(defineStatus, iteratorRecord)。
      9. kk + 1。
  6. 注:items 不是可迭代对象,因此假定其为类数组对象
  7. arrayLike 为 ! ToObject(items)。
  8. len 为 ? LengthOfArrayLike(arrayLike)。
  9. 如果 IsConstructor(C) 为 true,则
    1. A 为 ? Construct(C, « 𝔽(len) »)。
  10. 否则,
    1. A 为 ? ArrayCreate(len)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, Pk)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? CreateDataPropertyOrThrow(A, Pk, mappedValue)。
    6. kk + 1。
  13. 执行 ? Set(A, "length", 𝔽(len), true)。
  14. 返回 A

该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数

23.1.2.2 Array.isArray ( arg )

当调用该函数时,执行以下步骤:

  1. 返回 ? IsArray(arg)。

23.1.2.3 Array.of ( ...items )

当调用该方法时,执行以下步骤:

  1. lenitems 中元素的数量。
  2. lenNumber𝔽(len)。
  3. Cthis 值。
  4. 如果 IsConstructor(C) 为 true,则
    1. A 为 ? Construct(C, « lenNumber »)。
  5. 否则,
    1. A 为 ? ArrayCreate(len)。
  6. k 为 0。
  7. 重复,直到 k < len
    1. kValueitems[k]。
    2. Pk 为 ! ToString(𝔽(k))。
    3. 执行 ? CreateDataPropertyOrThrow(A, Pk, kValue)。
    4. kk + 1。
  8. 执行 ? Set(A, "length", lenNumber, true)。
  9. 返回 A

该方法是有意设计为泛型工厂方法;它不要求其 this 值为 Array 构造函数。因此它可以被转移或继承到其它可用单一数字参数调用的构造函数

23.1.2.4 Array.prototype

Array.prototype 的值为数组原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.1.2.5 get Array [ %Symbol.species% ]

Array[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "get [Symbol.species]"

数组原型方法通常使用其 this 值的 constructor 来创建派生对象。然而,子类构造函数可以通过重写其 %Symbol.species% 属性来覆盖默认行为。

23.1.3 数组原型对象的属性

数组原型对象

  • %Array.prototype%
  • 数组特殊对象,并具有该类对象指定的内部方法。
  • 具有一个 "length" 属性,其初始值为+0𝔽,属性特性为 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。
  • 具有一个名为 [[Prototype]] 的内部槽,其值为 %Object.prototype%

数组原型对象被指定为数组特殊对象,以确保与 ECMAScript 2015 规范之前编写的 ECMAScript 代码兼容。

23.1.3.1 Array.prototype.at ( index )

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  5. 否则,
    1. klen + relativeIndex
  6. 如果 k < 0 或 klen,返回 undefined
  7. 返回 ? Get(O, ! ToString(𝔽(k)))。

23.1.3.2 Array.prototype.concat ( ...items )

该方法返回一个数组,包含该对象的数组元素后跟每个参数的数组元素。

调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. A 为 ? ArraySpeciesCreate(O, 0)。
  3. n 为 0。
  4. O 前置到 items
  5. items 的每个元素 E,执行
    1. spreadable 为 ? IsConcatSpreadable(E)。
    2. 如果 spreadabletrue,则
      1. len 为 ? LengthOfArrayLike(E)。
      2. 如果 n + len > 253 - 1,抛出 TypeError 异常。
      3. k 为 0。
      4. 重复,直到 k < len
        1. Pk 为 ! ToString(𝔽(k))。
        2. exists 为 ? HasProperty(E, Pk)。
        3. 如果 existstrue,则
          1. subElement 为 ? Get(E, Pk)。
          2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), subElement)。
        4. nn + 1。
        5. kk + 1。
    3. 否则,
      1. 注:E 作为单项加入而不是展开。
      2. 如果 n ≥ 253 - 1,抛出 TypeError 异常。
      3. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), E)。
      4. nn + 1。
  6. 执行 ? Set(A, "length", 𝔽(n), true)。
  7. 返回 A

该方法的 "length" 属性为 1𝔽

注 1

在步骤 6 中显式设置 "length" 属性,是为了确保当 items 的最后一个非空元素有尾部空洞或 A 不是内建数组时长度正确。

注 2

该方法被设计为泛型;不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.2.1 IsConcatSpreadable ( O )

抽象操作 IsConcatSpreadable 接收参数 O(一个 ECMAScript 语言值),并返回 包含 布尔值的正常完成,或 抛出完成。调用时执行以下步骤:

  1. 如果 O 不是对象,返回 false
  2. spreadable 为 ? Get(O, %Symbol.isConcatSpreadable%)。
  3. 如果 spreadable 不为 undefined,返回 ToBoolean(spreadable)。
  4. 返回 ? IsArray(O)。

23.1.3.3 Array.prototype.constructor

Array.prototype.constructor 的初始值为 %Array%

23.1.3.4 Array.prototype.copyWithin ( target, start [ , end ] )

注 1

end 参数是可选的。如果未提供,则使用 this 值的长度。

注 2

如果 target 为负数,则视为 length + target,其中 length 是数组的长度。如果 start 为负数,则视为 length + start。如果 end 为负数,则视为 length + end

调用该方法时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  4. 如果 relativeTarget = -∞,令 to 为 0。
  5. 否则如果 relativeTarget < 0,令 tomax(len + relativeTarget, 0)。
  6. 否则,令 tomin(relativeTarget, len)。
  7. relativeStart 为 ? ToIntegerOrInfinity(start)。
  8. 如果 relativeStart = -∞,令 from 为 0。
  9. 否则如果 relativeStart < 0,令 frommax(len + relativeStart, 0)。
  10. 否则,令 frommin(relativeStart, len)。
  11. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  12. 如果 relativeEnd = -∞,令 final 为 0。
  13. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  14. 否则,令 finalmin(relativeEnd, len)。
  15. countmin(final - from, len - to)。
  16. 如果 from < toto < from + count,则
    1. direction 为 -1。
    2. 设置 fromfrom + count - 1。
    3. 设置 toto + count - 1。
  17. 否则,
    1. direction 为 1。
  18. 重复,直到 count > 0,
    1. fromKey 为 ! ToString(𝔽(from))。
    2. toKey 为 ! ToString(𝔽(to))。
    3. fromPresent 为 ? HasProperty(O, fromKey)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(O, fromKey)。
      2. 执行 ? Set(O, toKey, fromValue, true)。
    5. 否则,
      1. 断言fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(O, toKey)。
    6. 设置 fromfrom + direction
    7. 设置 toto + direction
    8. 设置 countcount - 1。
  19. 返回 O
注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.5 Array.prototype.entries ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, key+value)。

23.1.3.6 Array.prototype.every ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数并返回可转换为布尔值的函数。every 会按升序对数组中实际存在的每个元素调用 callback 一次,直到遇到一个 callback 返回 false 的元素。如果找到这样的元素,every 会立即返回 false。否则,every 返回 truecallback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

every 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

every 处理的元素范围在第一次调用 callback 前就已确定。调用 every 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 every 访问该元素时的值;在 every 调用开始后被删除且尚未被访问的元素不会被访问。every 的行为类似于数学中的“全称量词”。特别地,对于空数组,它返回 true

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 testResultfalse,返回 false
    4. 设置 kk + 1。
  6. 返回 true
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.7 Array.prototype.fill ( value [ , start [ , end ] ] )

注 1

start 参数是可选的。如果未提供,则使用 +0𝔽

end 参数是可选的。如果未提供,则使用 this 值的长度。

注 2

如果 start 为负数,则视为 length + start,其中 length 是数组的长度。如果 end 为负数,则视为 length + end

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. 重复,直到 k < final
    1. Pk 为 ! ToString(𝔽(k))。
    2. 执行 ? Set(O, Pk, value, true)。
    3. kk + 1。
  12. 返回 O
注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.8 Array.prototype.filter ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数并返回可转换为布尔值的函数。filter 会按升序对数组中每个元素调用 callback 一次,并构造一个包含所有 callback 返回 true 的值的新数组。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

filter 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

filter 处理的元素范围在第一次调用 callback 前就已确定。调用 filter 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 filter 访问该元素时的值;在 filter 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, 0)。
  5. k 为 0。
  6. to 为 0。
  7. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 selectedtrue,则
        1. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(to)), kValue)。
        2. 设置 toto + 1。
    4. 设置 kk + 1。
  8. 返回 A
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.9 Array.prototype.find ( predicate [ , thisArg ] )

注 1

该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,find 会立即返回该元素的值。否则,find 返回 undefined

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.10 Array.prototype.findIndex ( predicate [ , thisArg ] )

注 1

该方法会按索引升序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findIndex 会立即返回该元素的索引。否则,findIndex 返回 -1。

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.11 Array.prototype.findLast ( predicate [ , thisArg ] )

注 1

该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findLast 会立即返回该元素的值。否则,findLast 返回 undefined

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Value]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。

23.1.3.12 Array.prototype.findLastIndex ( predicate [ , thisArg ] )

注 1

该方法会按索引降序对数组的每个元素调用 predicate 一次,直到找到一个 predicate 返回可转换为 true 的值的元素。如果找到这样的元素,findLastIndex 会立即返回该元素的索引。否则,findLastIndex 返回 -1。

更多信息见 FindViaPredicate

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  4. 返回 findRec.[[Index]]
注 2

该方法被设计为泛型;它不要求其 this 值为数组对象。因此它可以转移到其他类型对象用作方法。

23.1.3.12.1 FindViaPredicate ( O, len, direction, predicate, thisArg )

抽象操作 FindViaPredicate 接收参数 O(一个对象)、len(一个非负整数)、directionascendingdescending)、predicate(一个ECMAScript 语言值)、和 thisArg(一个ECMAScript 语言值),返回一个包含字段 [[Index]](一个整数)和 [[Value]](一个ECMAScript 语言值)的记录,或抛出完成类型的 异常

O 应为类数组对象TypedArray。该操作会按 direction 指示的顺序(升序或降序)对 O 的每个元素调用 predicate,直到找到一个 predicate 返回可转换为 true 的值的元素。此时,该操作返回一个包含所找到元素索引和值的记录。如果未找到这样的元素,则返回一个 记录,其索引为 -1𝔽,值为 undefined

predicate 应为一个函数。对数组的每个元素调用时,传递三个参数:元素的值、元素的索引和被遍历的对象。其返回值会被转换为布尔值。

thisArg 会作为每次调用 predicate 时的 this 值。

该操作不会直接修改其调用的对象,但该对象可能会被 predicate 的调用修改。

处理的元素范围在首次调用 predicate 前(遍历开始前)就已确定。遍历后添加到数组的元素不会被 predicate 访问。如果数组中已存在的元素被修改,则传递给 predicate 的值为操作访问该元素时的值。在遍历开始后被删除且尚未被访问的元素依然会被访问,要么从原型获取,要么为 undefined

调用时执行以下步骤:

  1. 如果 IsCallable(predicate) 为 false,抛出 TypeError 异常。
  2. 如果 directionascending,则
    1. indices 为从 0(含)到 len(不含)区间内所有整数按升序排列的列表
  3. 否则,
    1. indices 为从 0(含)到 len(不含)区间内所有整数按降序排列的列表
  4. 对于 indices 中的每个整数 k,执行
    1. Pk 为 ! ToString(𝔽(k))。
    2. 注:如果 OTypedArray,则下面对 Get 的调用会返回正常完成类型。
    3. kValue 为 ? Get(O, Pk)。
    4. testResult 为 ? Call(predicate, thisArg, « kValue, 𝔽(k), O »)。
    5. 如果 ToBoolean(testResult) 为 true,则返回 记录 { [[Index]]: 𝔽(k), [[Value]]: kValue }。
  5. 返回 记录 { [[Index]]: -1𝔽, [[Value]]: undefined }.

23.1.3.13 Array.prototype.flat ( [ depth ] )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. sourceLen 为 ? LengthOfArrayLike(O)。
  3. depthNum 为 1。
  4. 如果 depth 不等于 undefined,则
    1. 设置 depthNum 为 ? ToIntegerOrInfinity(depth)。
    2. 如果 depthNum < 0,设置 depthNum 为 0。
  5. A 为 ? ArraySpeciesCreate(O, 0)。
  6. 执行 ? FlattenIntoArray(A, O, sourceLen, 0, depthNum)。
  7. 返回 A

23.1.3.13.1 FlattenIntoArray ( target, source, sourceLen, start, depth [ , mapperFunction [ , thisArg ] ] )

抽象操作 FlattenIntoArray 接收参数 target(一个对象)、source(一个对象)、sourceLen(一个非负整数)、start(一个非负整数)、depth(一个非负整数或+∞),可选参数 mapperFunction(一个函数对象)、thisArg(一个ECMAScript 语言值),返回包含非负整数的正常完成,或抛出完成。调用时执行以下步骤:

  1. 断言:如果 mapperFunction 存在,则 IsCallable(mapperFunction) 为 truethisArg 存在,且 depth 为 1。
  2. targetIndexstart
  3. sourceIndex+0𝔽
  4. 重复,直到 (sourceIndex) < sourceLen
    1. P 为 ! ToString(sourceIndex)。
    2. exists 为 ? HasProperty(source, P)。
    3. 如果 existstrue,则
      1. element 为 ? Get(source, P)。
      2. 如果 mapperFunction 存在,则
        1. 设置 element 为 ? Call(mapperFunction, thisArg, « element, sourceIndex, source »)。
      3. shouldFlattenfalse
      4. 如果 depth > 0,则
        1. 设置 shouldFlatten 为 ? IsArray(element)。
      5. 如果 shouldFlattentrue,则
        1. 如果 depth = +∞,令 newDepth 为 +∞。
        2. 否则,令 newDepthdepth - 1。
        3. elementLen 为 ? LengthOfArrayLike(element)。
        4. 设置 targetIndex 为 ? FlattenIntoArray(target, element, elementLen, targetIndex, newDepth)。
      6. 否则,
        1. 如果 targetIndex ≥ 253 - 1,抛出 TypeError 异常。
        2. 执行 ? CreateDataPropertyOrThrow(target, ! ToString(𝔽(targetIndex)), element)。
        3. 设置 targetIndextargetIndex + 1。
    4. 设置 sourceIndexsourceIndex + 1𝔽
  5. 返回 targetIndex

23.1.3.14 Array.prototype.flatMap ( mapperFunction [ , thisArg ] )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. sourceLen 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(mapperFunction) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, 0)。
  5. 执行 ? FlattenIntoArray(A, O, sourceLen, 0, 1, mapperFunction, thisArg)。
  6. 返回 A

23.1.3.15 Array.prototype.forEach ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数的函数。forEach 对数组中实际存在的每个元素按升序调用 callback 一次。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

forEach 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

forEach 处理的元素范围在第一次调用 callback 前就已确定。调用 forEach 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 forEach 访问该元素时的值;在 forEach 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  6. 返回 undefined
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.16 Array.prototype.includes ( searchElement [ , fromIndex ] )

注 1

该方法会按升序将 searchElement 与数组的元素进行比较,使用 SameValueZero 算法,如果在任何位置找到,则返回 true;否则返回 false

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于等于数组长度,则返回 false,即不会搜索数组。如果小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则会搜索整个数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 false
  4. n 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 n 为 0。
  6. 如果 n = +∞,返回 false
  7. 否则如果 n = -∞,设置 n 为 0。
  8. 如果 n ≥ 0,则
    1. kn
  9. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  10. 重复,直到 k < len
    1. elementK 为 ? Get(O, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 为 true,返回 true
    3. 设置 kk + 1。
  11. 返回 false
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

注 3

该方法有意与类似的 indexOf 方法有两点不同。第一,它使用 SameValueZero 算法,而不是 IsStrictlyEqual,从而可以检测 NaN 数组元素。第二,它不会跳过缺失的数组元素,而是将它们视为 undefined

23.1.3.17 Array.prototype.indexOf ( searchElement [ , fromIndex ] )

该方法使用 IsStrictlyEqual 算法,按升序将 searchElement 与数组中的元素进行比较,如果在一个或多个索引处找到,则返回最小的那个索引;否则返回 -1𝔽

注 1

可选的第二个参数 fromIndex 默认为 +0𝔽(即搜索整个数组)。如果它大于等于数组长度,则返回 -1𝔽,即不会搜索数组。如果它小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则会搜索整个数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 -1𝔽
  4. n 为 ? ToIntegerOrInfinity(fromIndex)。
  5. 断言:如果 fromIndexundefined,则 n 为 0。
  6. 如果 n = +∞,返回 -1𝔽
  7. 否则如果 n = -∞,设置 n 为 0。
  8. 如果 n ≥ 0,则
    1. kn
  9. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  10. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk + 1。
  11. 返回 -1𝔽
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.18 Array.prototype.join ( separator )

该方法将数组的元素转换为字符串,然后用 separator 分隔这些字符串并连接起来。如果没有提供分隔符,则使用单个逗号作为分隔符。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 separatorundefined,令 sep","
  4. 否则,令 sep 为 ? ToString(separator)。
  5. R 为空字符串。
  6. k 为 0。
  7. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rsep 的结果。
    2. element 为 ? Get(O, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. S 为 ? ToString(element)。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  8. 返回 R

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.19 Array.prototype.keys ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, key)。

23.1.3.20 Array.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

注 1

该方法会按降序将 searchElement 与数组的元素比较,使用 IsStrictlyEqual 算法,如果在一个或多个索引处找到,则返回最大的那个索引;否则返回 -1𝔽

可选的第二个参数 fromIndex 默认为数组长度减一(即搜索整个数组)。如果它大于等于数组长度,则会搜索整个数组。如果它小于 -0𝔽,则用作从数组末尾的偏移来计算 fromIndex。如果计算得到的索引小于等于 +0𝔽,则返回 -1𝔽

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,返回 -1𝔽
  4. 如果 fromIndex 存在,令 n 为 ? ToIntegerOrInfinity(fromIndex); 否则令 nlen - 1。
  5. 如果 n = -∞,返回 -1𝔽
  6. 如果 n ≥ 0,则
    1. kmin(n, len - 1)。
  7. 否则,
    1. klen + n
  8. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ? Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk - 1。
  9. 返回 -1𝔽
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.21 Array.prototype.map ( callback [ , thisArg ] )

注 1

callback 应该是一个接受三个参数的函数。map 会按升序对数组中每个元素调用 callback 一次,并用结果构造一个新数组。callback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

map 不会直接修改它所调用的对象,但该对象可能会被 callback 的调用修改。

map 处理的元素范围在第一次调用 callback 前就已确定。调用 map 之后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 map 访问该元素时的值;在 map 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. A 为 ? ArraySpeciesCreate(O, len)。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
      3. 执行 ? CreateDataPropertyOrThrow(A, Pk, mappedValue)。
    4. 设置 kk + 1。
  7. 返回 A
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.22 Array.prototype.pop ( )

注 1

该方法移除数组的最后一个元素并返回它。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,则
    1. 执行 ? Set(O, "length", +0𝔽, true)。
    2. 返回 undefined
  4. 否则,
    1. 断言len > 0。
    2. newLen𝔽(len - 1)。
    3. index 为 ! ToString(newLen)。
    4. element 为 ? Get(O, index)。
    5. 执行 ? DeletePropertyOrThrow(O, index)。
    6. 执行 ? Set(O, "length", newLen, true)。
    7. 返回 element
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.23 Array.prototype.push ( ...items )

注 1

该方法将参数按出现顺序追加到数组末尾。它返回数组的新长度。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. argCountitems 中元素的数量。
  4. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
  5. 对于 items 的每个元素 E,执行
    1. 执行 ? Set(O, ! ToString(𝔽(len)), E, true)。
    2. 设置 lenlen + 1。
  6. 执行 ? Set(O, "length", 𝔽(len), true)。
  7. 返回 𝔽(len)。

该方法的 "length" 属性为 1𝔽

注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.24 Array.prototype.reduce ( callback [ , initialValue ] )

注 1

callback 应为一个接受四个参数的函数。reduce 会对数组中第一个元素之后的每个元素按升序以函数形式调用 callback 一次。

callback 被调用时带四个参数:previousValue(上次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 和被遍历的对象。首次调用 callback 时,previousValuecurrentValue 可能有两种情况。如果调用 reduce 时提供了 initialValue,则 previousValueinitialValuecurrentValue 为数组的第一个值。如果没有提供 initialValue,则 previousValue 为数组的第一个值,currentValue 为第二个值。如果数组为空且未提供 initialValue,会抛出 TypeError

reduce 不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。

reduce 处理的元素范围在第一次调用 callback 前就已确定。调用 reduce 后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值为 reduce 访问该元素时的值;在 reduce 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. k 为 0。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. 设置 accumulatorinitialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,直到 kPresentfalsek < len
      1. Pk 为 ! ToString(𝔽(k))。
      2. 设置 kPresent 为 ? HasProperty(O, Pk)。
      3. 如果 kPresenttrue,则
        1. 设置 accumulator 为 ? Get(O, Pk)。
      4. 设置 kk + 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 设置 accumulator 为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  10. 返回 accumulator
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.25 Array.prototype.reduceRight ( callback [ , initialValue ] )

注 1

callback 应为一个接受四个参数的函数。reduceRight 会对数组中第一个元素之后的每个元素按降序以函数形式调用 callback 一次。

callback 被调用时带四个参数:previousValue(上次调用 callback 的值)、currentValue(当前元素的值)、currentIndex 和被遍历的对象。首次调用该函数时,previousValuecurrentValue 可能有两种情况。如果调用 reduceRight 时提供了 initialValue,则 previousValueinitialValuecurrentValue 为数组的最后一个值。如果没有提供 initialValue,则 previousValue 为数组的最后一个值,currentValue 为倒数第二个值。如果数组为空且未提供 initialValue,会抛出 TypeError

reduceRight 不会直接修改其调用的对象,但对象可能会被 callback 的调用修改。

reduceRight 处理的元素范围在第一次调用 callback 前就已确定。调用 reduceRight 后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被 callback 修改,则传递给 callback 的值为 reduceRight 访问该元素时的值;在 reduceRight 调用开始后被删除且尚未被访问的元素不会被访问。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. 如果 len = 0 且 initialValue 不存在,抛出 TypeError 异常。
  5. klen - 1。
  6. accumulatorundefined
  7. 如果 initialValue 存在,则
    1. 设置 accumulatorinitialValue
  8. 否则,
    1. kPresentfalse
    2. 重复,直到 kPresentfalsek ≥ 0,
      1. Pk 为 ! ToString(𝔽(k))。
      2. 设置 kPresent 为 ? HasProperty(O, Pk)。
      3. 如果 kPresenttrue,则
        1. 设置 accumulator 为 ? Get(O, Pk)。
      4. 设置 kk - 1。
    3. 如果 kPresentfalse,抛出 TypeError 异常。
  9. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 设置 accumulator 为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk - 1。
  10. 返回 accumulator
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.26 Array.prototype.reverse ( )

注 1

该方法重新排列数组元素,使其顺序颠倒。它返回反转后的数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. middlefloor(len / 2)。
  4. lower 为 0。
  5. 重复,直到 lowermiddle
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerExists 为 ? HasProperty(O, lowerP)。
    5. 如果 lowerExiststrue,则
      1. lowerValue 为 ? Get(O, lowerP)。
    6. upperExists 为 ? HasProperty(O, upperP)。
    7. 如果 upperExiststrue,则
      1. upperValue 为 ? Get(O, upperP)。
    8. 如果 lowerExiststrueupperExiststrue,则
      1. 执行 ? Set(O, lowerP, upperValue, true)。
      2. 执行 ? Set(O, upperP, lowerValue, true)。
    9. 否则如果 lowerExistsfalseupperExiststrue,则
      1. 执行 ? Set(O, lowerP, upperValue, true)。
      2. 执行 ? DeletePropertyOrThrow(O, upperP)。
    10. 否则如果 lowerExiststrueupperExistsfalse,则
      1. 执行 ? DeletePropertyOrThrow(O, lowerP)。
      2. 执行 ? Set(O, upperP, lowerValue, true)。
    11. 否则,
      1. 断言lowerExistsupperExists 都为 false
      2. 注:无操作需要执行。
    12. 设置 lowerlower + 1。
  6. 返回 O
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.27 Array.prototype.shift ( )

该方法移除数组的第一个元素并返回它。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 len = 0,则
    1. 执行 ? Set(O, "length", +0𝔽, true)。
    2. 返回 undefined
  4. first 为 ? Get(O, "0")。
  5. k 为 1。
  6. 重复,直到 k < len
    1. from 为 ! ToString(𝔽(k))。
    2. to 为 ! ToString(𝔽(k - 1))。
    3. fromPresent 为 ? HasProperty(O, from)。
    4. 如果 fromPresenttrue,则
      1. fromValue 为 ? Get(O, from)。
      2. 执行 ? Set(O, to, fromValue, true)。
    5. 否则,
      1. 断言fromPresentfalse
      2. 执行 ? DeletePropertyOrThrow(O, to)。
    6. 设置 kk + 1。
  7. 执行 ? DeletePropertyOrThrow(O, ! ToString(𝔽(len - 1)))。
  8. 执行 ? Set(O, "length", 𝔽(len - 1), true)。
  9. 返回 first

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.28 Array.prototype.slice ( start, end )

该方法返回一个包含数组从元素 start 到(但不包括)元素 end 的元素的新数组(如果 endundefined,则一直到数组末尾)。如果 start 为负数,则视为 length + start,其中 length 是数组长度。如果 end 为负数,则视为 length + end,其中 length 是数组长度。

调用时按照以下步骤执行:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 k 为 0。
  5. 否则如果 relativeStart < 0,令 kmax(len + relativeStart, 0)。
  6. 否则,令 kmin(relativeStart, len)。
  7. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  8. 如果 relativeEnd = -∞,令 final 为 0。
  9. 否则如果 relativeEnd < 0,令 finalmax(len + relativeEnd, 0)。
  10. 否则,令 finalmin(relativeEnd, len)。
  11. countmax(final - k, 0)。
  12. A 为 ? ArraySpeciesCreate(O, count)。
  13. n 为 0。
  14. 重复,直到 k < final
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(n)), kValue)。
    4. 设置 kk + 1。
    5. 设置 nn + 1。
  15. 执行 ? Set(A, "length", 𝔽(n), true)。
  16. 返回 A
注 1

15 步显式设置 "length" 属性,旨在确保即使 A 不是内建数组时长度也是正确的。

注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.29 Array.prototype.some ( callback [ , thisArg ] )

注 1

callback 应为一个接受三个参数并返回可转换为布尔值的函数。some 会对数组中实际存在的每个元素按升序调用 callback,直到找到一个 callback 返回 true 的元素为止。如果找到这样的元素,some 会立即返回 true。否则,some 返回 falsecallback 只会对数组中实际存在的元素调用,不会对数组中缺失的元素调用。

如果提供了 thisArg 参数,则每次调用 callback 时都会用作 this 值。如果未提供,则使用 undefined

callback 被调用时有三个参数:元素的值、元素的索引、被遍历的对象。

some 不会直接修改其调用的对象,但该对象可能会被 callback 的调用修改。

some 处理的元素范围在第一次调用 callback 前就已确定。调用 some 后添加到数组的元素不会被 callback 访问。如果数组中已存在的元素被修改,则传递给 callback 的值是在 some 访问该元素时的值;在 some 调用开始后被删除且尚未被访问的元素不会被访问。some 类似于数学中的“存在”量词。特别地,对于空数组,它返回 false

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. k 为 0。
  5. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ? HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. kValue 为 ? Get(O, Pk)。
      2. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
      3. 如果 testResulttrue,返回 true
    4. 设置 kk + 1。
  6. 返回 false
注 2

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.30 Array.prototype.sort ( comparator )

该方法对数组的元素进行排序。如果 comparator 不为 undefined,则应为一个接受两个参数 xy 的函数,若 x < y,返回负数;若 x > y,返回正数;否则返回零。

调用时按照以下步骤执行:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. obj 为 ? ToObject(this 值)。
  3. len 为 ? LengthOfArrayLike(obj)。
  4. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  5. sortedList 为 ? SortIndexedProperties(obj, len, SortCompare, skip-holes)。
  6. itemCountsortedList 中元素的数量。
  7. j 为 0。
  8. 重复,直到 j < itemCount
    1. 执行 ? Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  9. 注:第 SortIndexedProperties 步骤(见 5)使用 skip-holes。剩余索引会被删除,以保留排序前检测到并排除的空洞数量。
  10. 重复,直到 j < len
    1. 执行 ? DeletePropertyOrThrow(obj, ! ToString(𝔽(j)))。
    2. 设置 jj + 1。
  11. 返回 obj
注 1

由于不存在的属性值总是大于 undefined 属性值,而 undefined 总是大于任何其他值(见 CompareArrayElements),undefined 属性值总是排序到结果的末尾,其后是不存在的属性值。

注 2

在第 56 步骤中由 ToString 抽象操作 执行的方法调用,可能导致 SortCompare 行为不是一个 一致性比较器

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此,它可以被转移到其他类型的对象上用作方法。

23.1.3.30.1 SortIndexedProperties ( obj, len, SortCompare, holes )

抽象操作 SortIndexedProperties 接收参数 obj(一个对象)、len(一个非负整数)、SortCompare(一个带有两个参数的抽象闭包)、holesskip-holesread-through-holes),返回包含List 的正常完成,或抛出完成。调用时执行以下步骤:

  1. items 为一个新的空List
  2. k 为 0。
  3. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 holesskip-holes,则
      1. kRead 为 ? HasProperty(obj, Pk)。
    3. 否则,
      1. 断言holesread-through-holes
      2. kReadtrue
    4. 如果 kReadtrue,则
      1. kValue 为 ? Get(obj, Pk)。
      2. kValue 添加到 items
    5. 设置 kk + 1。
  4. 使用实现定义SortCompare 的调用序列items 进行排序。如果此过程中有任何调用返回 异常完成,则在进行任何进一步调用 SortCompare 前停止并返回该 Completion Record
  5. 返回 items

排序顺序(sort order)指的是上述算法中第 4 步执行后 items 的排列顺序。若 SortCompare 不是 items 元素的 一致性比较器,则 排序顺序实现定义。当通过 Array.prototype.sortArray.prototype.toSorted 调用 SortIndexedProperties 时,如果 comparatorundefined,且所有传给 SortCompare 的特定参数的 ToString 调用结果不一致,则 排序顺序 也是 实现定义

除非 排序顺序 被指定为 实现定义,否则必须满足以下所有条件:

  • 存在对小于 itemCount 的非负整数的某个数学排列 π,使得对于每个小于 itemCount 的非负整数 j,有 old[j]new[π(j)] 完全一致。
  • 对所有小于 itemCount 的非负整数 jk,如果 (SortCompare(old[j], old[k])) < 0,则 π(j) < π(k)
  • 对所有 j < k < itemCount 的非负整数 jk,如果 (SortCompare(old[j], old[k])) = 0,则 π(j) < π(k);即排序是稳定的。

此处记号 old[j] 表示第 4 步执行前 items[j],而 new[j] 表示执行后 items[j]。

抽象闭包或函数 comparator 对于值集合 S 来说,如果对集合 S 中所有可能的值 abc(可能相同)均满足以下要求,则称其为 一致性比较器。记号 a <C b 表示 (comparator(a, b)) < 0a =C b 表示 (comparator(a, b)) = 0a >C b 表示 (comparator(a, b)) > 0

  • 对于给定的 ab,每次调用 comparator(a, b) 总是返回相同的值 v。此外,v 是一个 Number,且 v 不是 NaN。这意味着对于一对 aba <C ba =C ba >C b 三者必有其一为真。
  • 调用 comparator(a, b) 不会修改 obj 或其原型链上的任何对象。
  • a =C a(自反性)
  • 如果 a =C b,则 b =C a(对称性)
  • 如果 a =C bb =C c,则 a =C c(传递性)
  • 如果 a <C bb <C c,则 a <C c(传递性)
  • 如果 a >C bb >C c,则 a >C c(传递性)

上述条件是保证 comparator 将集合 S 划分为等价类并且这些等价类是全序所必需且充分的条件。

23.1.3.30.2 CompareArrayElements ( x, y, comparator )

抽象操作 CompareArrayElements 接收参数 x(一个ECMAScript 语言值)、y(一个ECMAScript 语言值)、comparator(一个函数对象undefined),返回包含Number 的正常完成,或异常完成。调用时执行以下步骤:

  1. 如果 xy 都是 undefined,返回 +0𝔽
  2. 如果 xundefined,返回 1𝔽
  3. 如果 yundefined,返回 -1𝔽
  4. 如果 comparator 不为 undefined,则
    1. v 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 vNaN,返回 +0𝔽
    3. 返回 v
  5. xString 为 ? ToString(x)。
  6. yString 为 ? ToString(y)。
  7. xSmaller 为 ! IsLessThan(xString, yString, true)。
  8. 如果 xSmallertrue,返回 -1𝔽
  9. ySmaller 为 ! IsLessThan(yString, xString, true)。
  10. 如果 ySmallertrue,返回 1𝔽
  11. 返回 +0𝔽

23.1.3.31 Array.prototype.splice ( start, deleteCount, ...items )

注 1

该方法从整数索引 start 开始,删除数组中的 deleteCount 个元素,并用 items 的元素替换它们。它返回一个包含被删除元素(如有)的数组。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. itemCountitems 中元素的数量。
  8. 如果未传入 start,则
    1. actualDeleteCount 为 0。
  9. 否则如果未传入 deleteCount,则
    1. actualDeleteCountlen - actualStart
  10. 否则,
    1. dc 为 ? ToIntegerOrInfinity(deleteCount)。
    2. actualDeleteCount 为将 dc 限制在 0 到 len - actualStart 之间的结果。
  11. 如果 len + itemCount - actualDeleteCount > 253 - 1,抛出 TypeError 异常。
  12. A 为 ? ArraySpeciesCreate(O, actualDeleteCount)。
  13. k 为 0。
  14. 重复,直到 k < actualDeleteCount
    1. from 为 ! ToString(𝔽(actualStart + k))。
    2. 如果 ? HasProperty(O, from) 为 true,则
      1. fromValue 为 ? Get(O, from)。
      2. 执行 ? CreateDataPropertyOrThrow(A, ! ToString(𝔽(k)), fromValue)。
    3. 设置 kk + 1。
  15. 执行 ? Set(A, "length", 𝔽(actualDeleteCount), true)。
  16. 如果 itemCount < actualDeleteCount,则
    1. 设置 kactualStart
    2. 重复,直到 k < (len - actualDeleteCount),
      1. from 为 ! ToString(𝔽(k + actualDeleteCount))。
      2. to 为 ! ToString(𝔽(k + itemCount))。
      3. 如果 ? HasProperty(O, from) 为 true,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(O, to)。
      5. 设置 kk + 1。
    3. 设置 klen
    4. 重复,直到 k > (len - actualDeleteCount + itemCount),
      1. 执行 ? DeletePropertyOrThrow(O, ! ToString(𝔽(k - 1)))。
      2. 设置 kk - 1。
  17. 否则如果 itemCount > actualDeleteCount,则
    1. 设置 k 为 (len - actualDeleteCount)。
    2. 重复,直到 k > actualStart
      1. from 为 ! ToString(𝔽(k + actualDeleteCount - 1))。
      2. to 为 ! ToString(𝔽(k + itemCount - 1))。
      3. 如果 ? HasProperty(O, from) 为 true,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      4. 否则,
        1. 执行 ? DeletePropertyOrThrow(O, to)。
      5. 设置 kk - 1。
  18. 设置 kactualStart
  19. 对于 items 的每个元素 E,执行
    1. 执行 ? Set(O, ! ToString(𝔽(k)), E, true)。
    2. 设置 kk + 1。
  20. 执行 ? Set(O, "length", 𝔽(len - actualDeleteCount + itemCount), true)。
  21. 返回 A
注 2

在第 1520 步中显式设置 "length" 属性,旨在确保即使操作对象不是内建数组时长度也是正确的。

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.32 Array.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

包含 ECMA-402 国际化 API 的 ECMAScript 实现必须按照 ECMA-402 规范实现此方法。如果 ECMAScript 实现不包含 ECMA-402 API,则使用下面对该方法的规范。

注 1

ECMA-402 第一版未包含该方法的替代规范。

此方法的可选参数含义在 ECMA-402 规范中定义;不包含 ECMA-402 支持的实现不得将这些参数位置用于其他用途。

该方法调用时执行以下步骤:

  1. array 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(array)。
  3. separator 为适用于 宿主环境当前区域设置的 实现定义列表分隔符字符串值(如 ", ")。
  4. R 为空字符串。
  5. k 为 0。
  6. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rseparator 的结果。
    2. element 为 ? Get(array, ! ToString(𝔽(k)))。
    3. 如果 element 既不是 undefined 也不是 null,则
      1. S 为 ? ToString(? Invoke(element, "toLocaleString"))。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  7. 返回 R
注 2

该方法使用元素各自的 toLocaleString 方法将数组元素转换为字符串,然后用实现定义的、区分区域设置的分隔符字符串把这些字符串连接起来。此方法类似于 toString,但目的是生成符合 宿主环境当前区域习惯的本地化结果。

注 3

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.33 Array.prototype.toReversed ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. A 为 ? ArrayCreate(len)。
  4. k 为 0。
  5. 重复,直到 k < len
    1. from 为 ! ToString(𝔽(len - k - 1))。
    2. Pk 为 ! ToString(𝔽(k))。
    3. fromValue 为 ? Get(O, from)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pk, fromValue)。
    5. 设置 kk + 1。
  6. 返回 A

23.1.3.34 Array.prototype.toSorted ( comparator )

该方法调用时执行以下步骤:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. O 为 ? ToObject(this 值)。
  3. len 为 ? LengthOfArrayLike(O)。
  4. A 为 ? ArrayCreate(len)。
  5. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareArrayElements(x, y, comparator)。
  6. sortedList 为 ? SortIndexedProperties(O, len, SortCompare, read-through-holes)。
  7. j 为 0。
  8. 重复,直到 j < len
    1. 执行 ! CreateDataPropertyOrThrow(A, ! ToString(𝔽(j)), sortedList[j])。
    2. 设置 jj + 1。
  9. 返回 A

23.1.3.35 Array.prototype.toSpliced ( start, skipCount, ...items )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeStart 为 ? ToIntegerOrInfinity(start)。
  4. 如果 relativeStart = -∞,令 actualStart 为 0。
  5. 否则如果 relativeStart < 0,令 actualStartmax(len + relativeStart, 0)。
  6. 否则,令 actualStartmin(relativeStart, len)。
  7. insertCountitems 中元素的数量。
  8. 如果未传入 start,则
    1. actualSkipCount 为 0。
  9. 否则如果未传入 skipCount,则
    1. actualSkipCountlen - actualStart
  10. 否则,
    1. sc 为 ? ToIntegerOrInfinity(skipCount)。
    2. actualSkipCount 为将 sc 限制在 0 到 len - actualStart 之间的结果。
  11. newLenlen + insertCount - actualSkipCount
  12. 如果 newLen > 253 - 1,抛出 TypeError 异常。
  13. A 为 ? ArrayCreate(newLen)。
  14. i 为 0。
  15. ractualStart + actualSkipCount
  16. 重复,直到 i < actualStart
    1. Pi 为 ! ToString(𝔽(i))。
    2. iValue 为 ? Get(O, Pi)。
    3. 执行 ! CreateDataPropertyOrThrow(A, Pi, iValue)。
    4. 设置 ii + 1。
  17. 对于 items 的每个元素 E,执行
    1. Pi 为 ! ToString(𝔽(i))。
    2. 执行 ! CreateDataPropertyOrThrow(A, Pi, E)。
    3. 设置 ii + 1。
  18. 重复,直到 i < newLen
    1. Pi 为 ! ToString(𝔽(i))。
    2. from 为 ! ToString(𝔽(r))。
    3. fromValue 为 ? Get(O, from)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pi, fromValue)。
    5. 设置 ii + 1。
    6. 设置 rr + 1。
  19. 返回 A

23.1.3.36 Array.prototype.toString ( )

该方法调用时执行以下步骤:

  1. array 为 ? ToObject(this 值)。
  2. func 为 ? Get(array, "join")。
  3. 如果 IsCallable(func) 为 false,则将 func 设为内建函数 %Object.prototype.toString%。
  4. 返回 ? Call(func, array)。

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.37 Array.prototype.unshift ( ...items )

该方法将参数添加到数组的开头,其在数组中的顺序与参数列表中的顺序相同。

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. argCountitems 中元素的数量。
  4. 如果 argCount > 0,则
    1. 如果 len + argCount > 253 - 1,抛出 TypeError 异常。
    2. klen
    3. 重复,直到 k > 0,
      1. from 为 ! ToString(𝔽(k - 1))。
      2. to 为 ! ToString(𝔽(k + argCount - 1))。
      3. fromPresent 为 ? HasProperty(O, from)。
      4. 如果 fromPresenttrue,则
        1. fromValue 为 ? Get(O, from)。
        2. 执行 ? Set(O, to, fromValue, true)。
      5. 否则,
        1. 断言: fromPresentfalse
        2. 执行 ? DeletePropertyOrThrow(O, to)。
      6. 设置 kk - 1。
    4. j+0𝔽
    5. 对于 items 的每个元素 E,执行
      1. 执行 ? Set(O, ! ToString(j), E, true)。
      2. 设置 jj + 1𝔽
  5. 执行 ? Set(O, "length", 𝔽(len + argCount), true)。
  6. 返回 𝔽(len + argCount)。

该方法的 "length" 属性为 1𝔽

该方法被设计为泛型;它不要求其 this 值为数组。因此它可以转移到其他类型对象用作方法。

23.1.3.38 Array.prototype.values ( )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. 返回 CreateArrayIterator(O, value)。

23.1.3.39 Array.prototype.with ( index, value )

该方法调用时执行以下步骤:

  1. O 为 ? ToObject(this 值)。
  2. len 为 ? LengthOfArrayLike(O)。
  3. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  4. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  5. 否则,令 actualIndexlen + relativeIndex
  6. 如果 actualIndexlenactualIndex < 0,抛出 RangeError 异常。
  7. A 为 ? ArrayCreate(len)。
  8. k 为 0。
  9. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuevalue
    3. 否则,令 fromValue 为 ? Get(O, Pk)。
    4. 执行 ! CreateDataPropertyOrThrow(A, Pk, fromValue)。
    5. 设置 kk + 1。
  10. 返回 A

23.1.3.40 Array.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %Array.prototype.values%,定义见 23.1.3.38

23.1.3.41 Array.prototype [ %Symbol.unscopables% ]

%Symbol.unscopables% 数据属性 的初始值为通过以下步骤创建的对象:

  1. unscopableListOrdinaryObjectCreate(null)。
  2. 执行 ! CreateDataPropertyOrThrow(unscopableList, "at", true)。
  3. 执行 ! CreateDataPropertyOrThrow(unscopableList, "copyWithin", true)。
  4. 执行 ! CreateDataPropertyOrThrow(unscopableList, "entries", true)。
  5. 执行 ! CreateDataPropertyOrThrow(unscopableList, "fill", true)。
  6. 执行 ! CreateDataPropertyOrThrow(unscopableList, "find", true)。
  7. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findIndex", true)。
  8. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLast", true)。
  9. 执行 ! CreateDataPropertyOrThrow(unscopableList, "findLastIndex", true)。
  10. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flat", true)。
  11. 执行 ! CreateDataPropertyOrThrow(unscopableList, "flatMap", true)。
  12. 执行 ! CreateDataPropertyOrThrow(unscopableList, "includes", true)。
  13. 执行 ! CreateDataPropertyOrThrow(unscopableList, "keys", true)。
  14. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toReversed", true)。
  15. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSorted", true)。
  16. 执行 ! CreateDataPropertyOrThrow(unscopableList, "toSpliced", true)。
  17. 执行 ! CreateDataPropertyOrThrow(unscopableList, "values", true)。
  18. 返回 unscopableList

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

该对象的自有属性名是在 ECMAScript 2015 规范之前未作为 Array.prototype 标准属性包含的属性名。这些名称在 with 语句绑定时会被忽略,以保持现有代码的行为,这些代码可能在外部作用域中使用其中的某个名称作为绑定,而该作用域被 with 语句(其绑定对象为数组)所遮蔽。

"with" 未被包含在 unscopableList 中的原因是它已经是一个 保留字

23.1.4 数组实例的属性

数组实例是 数组特异对象,并具有为此类对象指定的内部方法。数组实例继承自 Array 原型对象 的属性。

数组实例有一个 "length" 属性,以及一组带有 数组索引 名称的可枚举属性。

23.1.4.1 length

Array 实例的 "length" 属性是一个 数据属性,其值总是数值上大于每个名称为 数组索引、且可配置的自有属性的名称。

"length" 属性最初拥有属性 { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }。

减少 "length" 属性的值会导致删除其 数组索引 介于旧值和新值之间的自有数组元素。但不可配置属性不能被删除。试图将数组的 "length" 属性设置为小于或等于现有不可配置 数组索引属性的最大数值自有 属性名 时,length 会被设置为比该不可配置数值自有 属性名 大 1 的数值。见 10.4.2.1

23.1.5 数组迭代器对象

数组迭代器是一个表示对某个特定数组实例对象的特定迭代的对象。数组迭代器对象没有命名的 构造函数。数组迭代器对象是通过调用数组实例对象的某些方法创建的。

23.1.5.1 CreateArrayIterator ( array, kind )

抽象操作 CreateArrayIterator 接收参数 array(一个对象)和 kindkey+valuekeyvalue),返回一个对象。用于为返回此类 迭代器 的 Array 方法创建 迭代器对象。调用时执行以下步骤:

  1. iteratorOrdinaryObjectCreate(%ArrayIteratorPrototype%, « [[IteratedArrayLike]], [[ArrayLikeNextIndex]], [[ArrayLikeIterationKind]] »)。
  2. 设置 iterator.[[IteratedArrayLike]]array
  3. 设置 iterator.[[ArrayLikeNextIndex]] 为 0。
  4. 设置 iterator.[[ArrayLikeIterationKind]]kind
  5. 返回 iterator

23.1.5.2 %ArrayIteratorPrototype% 对象

%ArrayIteratorPrototype% 对象:

23.1.5.2.1 %ArrayIteratorPrototype%.next ( )

  1. Othis 值。
  2. 如果 O 不是对象,抛出 TypeError 异常。
  3. 如果 O 不具有 数组迭代器实例(23.1.5.3)的所有内部槽,抛出 TypeError 异常。
  4. arrayO.[[IteratedArrayLike]]
  5. 如果 arrayundefined,返回 CreateIteratorResultObject(undefined, true)。
  6. indexO.[[ArrayLikeNextIndex]]
  7. kindO.[[ArrayLikeIterationKind]]
  8. 如果 array 具有 [[TypedArrayName]] 内部槽,则
    1. taRecordMakeTypedArrayWithBufferWitnessRecord(array, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    3. lenTypedArrayLength(taRecord)。
  9. 否则,
    1. len 为 ? LengthOfArrayLike(array)。
  10. 如果 indexlen,则
    1. 设置 O.[[IteratedArrayLike]]undefined
    2. 返回 CreateIteratorResultObject(undefined, true)。
  11. 设置 O.[[ArrayLikeNextIndex]]index + 1。
  12. indexNumber𝔽(index)。
  13. 如果 kindkey,则
    1. resultindexNumber
  14. 否则,
    1. elementKey 为 ! ToString(indexNumber)。
    2. elementValue 为 ? Get(array, elementKey)。
    3. 如果 kindvalue,则
      1. resultelementValue
    4. 否则,
      1. 断言: kindkey+value
      2. resultCreateArrayFromListindexNumber, elementValue »)。
  15. 返回 CreateIteratorResultObject(result, false)。

23.1.5.2.2 %ArrayIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Array Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

23.1.5.3 数组迭代器实例的属性

数组迭代器实例是 普通对象,继承自 %ArrayIteratorPrototype% 内建对象的属性。数组迭代器实例创建时具有 表 74 中列出的内部槽。

表 74:数组迭代器实例的内部槽
内部槽 类型 描述
[[IteratedArrayLike]] 一个对象或 undefined 被迭代的 类数组对象
[[ArrayLikeNextIndex]] 非负整数 迭代器要检查的下一个元素的整数索引
[[ArrayLikeIterationKind]] key+valuekeyvalue 标识每次迭代返回什么类型值的值。

23.2 TypedArray 对象

TypedArray 展示了一个底层二进制数据缓冲区(25.1)的类数组视图。TypedArray 元素类型是所有 TypedArray 实例元素所具有的底层二进制标量数据类型。每种支持的元素类型都有一个不同的 TypedArray 构造函数,见 表 75表 75 中的每个 构造函数 都有一个对应的不同的原型对象。

表 75:TypedArray 构造函数
构造函数名称及内建对象 元素类型 元素大小 转换操作 描述
Int8Array
%Int8Array%
int8 1 ToInt8 8 位二进制补码有符号整数
Uint8Array
%Uint8Array%
uint8 1 ToUint8 8 位无符号整数
Uint8ClampedArray
%Uint8ClampedArray%
uint8clamped 1 ToUint8Clamp 8 位无符号整数(夹紧转换)
Int16Array
%Int16Array%
int16 2 ToInt16 16 位二进制补码有符号整数
Uint16Array
%Uint16Array%
uint16 2 ToUint16 16 位无符号整数
Int32Array
%Int32Array%
int32 4 ToInt32 32 位二进制补码有符号整数
Uint32Array
%Uint32Array%
uint32 4 ToUint32 32 位无符号整数
BigInt64Array
%BigInt64Array%
bigint64 8 ToBigInt64 64 位二进制补码有符号整数
BigUint64Array
%BigUint64Array%
biguint64 8 ToBigUint64 64 位无符号整数
Float16Array
%Float16Array%
float16 2 16 位 IEEE 浮点数
Float32Array
%Float32Array%
float32 4 32 位 IEEE 浮点数
Float64Array
%Float64Array%
float64 8 64 位 IEEE 浮点数

在下述定义中,对 TypedArray 的引用应替换为上表中相应的 构造函数 名称。

23.2.1 %TypedArray% 内建对象

%TypedArray% 内建对象:

23.2.1.1 %TypedArray% ( )

该函数被调用时执行以下步骤:

  1. 抛出 TypeError 异常。

该函数的 "length" 属性为 +0𝔽

23.2.2 %TypedArray% 内建对象的属性

%TypedArray% 内建对象:

  • 拥有一个 [[Prototype]] 内部槽,其值为 %Function.prototype%
  • 有一个 "name" 属性,其值为 "TypedArray"
  • 有如下属性:

23.2.2.1 %TypedArray%.from ( source [ , mapper [ , thisArg ] ] )

该方法被调用时执行以下步骤:

  1. Cthis 值。
  2. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  3. 如果 mapperundefined,则
    1. mappingfalse
  4. 否则,
    1. 如果 IsCallable(mapper) 为 false,抛出 TypeError 异常。
    2. mappingtrue
  5. usingIterator 为 ? GetMethod(source, %Symbol.iterator%).
  6. 如果 usingIterator 不为 undefined,则
    1. values 为 ? IteratorToList(? GetIteratorFromMethod(source, usingIterator))。
    2. lenvalues 中元素的数量。
    3. targetObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
    4. k 为 0。
    5. 重复,直到 k < len
      1. Pk 为 ! ToString(𝔽(k))。
      2. kValuevalues 的第一个元素。
      3. values 移除第一个元素。
      4. 如果 mappingtrue,则
        1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
      5. 否则,
        1. mappedValuekValue
      6. 执行 ? Set(targetObj, Pk, mappedValue, true)。
      7. 设置 kk + 1。
    6. 断言values 现在是一个空的 List
    7. 返回 targetObj
  7. 注:source 不是 可迭代对象,所以假定它已经是 类数组对象
  8. arrayLike 为 ! ToObject(source)。
  9. len 为 ? LengthOfArrayLike(arrayLike)。
  10. targetObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ? Get(arrayLike, Pk)。
    3. 如果 mappingtrue,则
      1. mappedValue 为 ? Call(mapper, thisArg, « kValue, 𝔽(k) »)。
    4. 否则,
      1. mappedValuekValue
    5. 执行 ? Set(targetObj, Pk, mappedValue, true)。
    6. 设置 kk + 1。
  13. 返回 targetObj

23.2.2.2 %TypedArray%.of ( ...items )

该方法被调用时执行以下步骤:

  1. lenitems 中元素的数量。
  2. Cthis 值。
  3. 如果 IsConstructor(C) 为 false,抛出 TypeError 异常。
  4. newObj 为 ? TypedArrayCreateFromConstructor(C, « 𝔽(len) »)。
  5. k 为 0。
  6. 重复,直到 k < len
    1. kValueitems[k]。
    2. Pk 为 ! ToString(𝔽(k))。
    3. 执行 ? Set(newObj, Pk, kValue, true)。
    4. 设置 kk + 1。
  7. 返回 newObj

23.2.2.3 %TypedArray%.prototype

%TypedArray%.prototype 的初始值为 %TypedArray% 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.2.4 get %TypedArray% [ %Symbol.species% ]

%TypedArray%[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "get [Symbol.species]"

%TypedArray.prototype% 的方法通常使用其 this 值的 构造函数 来创建派生对象。但是,子类构造函数可以通过重新定义其 %Symbol.species% 属性来覆盖该默认行为。

23.2.3 %TypedArray% 原型对象的属性

%TypedArray% 原型对象

  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • %TypedArray.prototype%
  • 是一个 普通对象
  • 没有 [[ViewedArrayBuffer]] 或其它 TypedArray 实例对象专有的内部槽。

23.2.3.1 %TypedArray%.prototype.at ( index )

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,则
    1. krelativeIndex
  6. 否则,
    1. klen + relativeIndex
  7. 如果 k < 0 或 klen,返回 undefined
  8. 返回 ! Get(O, ! ToString(𝔽(k)))。

23.2.3.2 get %TypedArray%.prototype.buffer

%TypedArray%.prototype.buffer 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. 返回 buffer

23.2.3.3 get %TypedArray%.prototype.byteLength

%TypedArray%.prototype.byteLength 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  5. sizeTypedArrayByteLength(taRecord)。
  6. 返回 𝔽(size)。

23.2.3.4 get %TypedArray%.prototype.byteOffset

%TypedArray%.prototype.byteOffset 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 具有 [[ViewedArrayBuffer]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,返回 +0𝔽
  6. offsetO.[[ByteOffset]]
  7. 返回 𝔽(offset)。

23.2.3.5 %TypedArray%.prototype.constructor

%TypedArray%.prototype.constructor 的初始值为 %TypedArray%

23.2.3.6 %TypedArray%.prototype.copyWithin ( target, start [ , end ] )

该方法的参数解释和用法与 23.1.3.4 中定义的 Array.prototype.copyWithin 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeTarget 为 ? ToIntegerOrInfinity(target)。
  5. 如果 relativeTarget = -∞,令 targetIndex 为 0。
  6. 否则如果 relativeTarget < 0,令 targetIndexmax(len + relativeTarget, 0)。
  7. 否则,令 targetIndexmin(relativeTarget, len)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, len)。
  12. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  13. 如果 relativeEnd = -∞,令 endIndex 为 0。
  14. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  15. 否则,令 endIndexmin(relativeEnd, len)。
  16. countmin(endIndex - startIndex, len - targetIndex)。
  17. 如果 count > 0,则
    1. 注:拷贝操作必须以保持源数据比特级编码的方式执行。
    2. bufferO.[[ViewedArrayBuffer]]
    3. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
    4. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    5. 设置 lenTypedArrayLength(taRecord)。
    6. elementSizeTypedArrayElementSize(O)。
    7. byteOffsetO.[[ByteOffset]]
    8. bufferByteLimit 为 (len × elementSize) + byteOffset
    9. toByteIndex 为 (targetIndex × elementSize) + byteOffset
    10. fromByteIndex 为 (startIndex × elementSize) + byteOffset
    11. countBytescount × elementSize
    12. 如果 fromByteIndex < toByteIndextoByteIndex < fromByteIndex + countBytes,则
      1. direction 为 -1。
      2. 设置 fromByteIndexfromByteIndex + countBytes - 1。
      3. 设置 toByteIndextoByteIndex + countBytes - 1。
    13. 否则,
      1. direction 为 1。
    14. 重复,直到 countBytes > 0,
      1. 如果 fromByteIndex < bufferByteLimittoByteIndex < bufferByteLimit,则
        1. valueGetValueFromBuffer(buffer, fromByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(buffer, toByteIndex, uint8, value, true, unordered)。
        3. 设置 fromByteIndexfromByteIndex + direction
        4. 设置 toByteIndextoByteIndex + direction
        5. 设置 countBytescountBytes - 1。
      2. 否则,
        1. 设置 countBytes 为 0。
  18. 返回 O

23.2.3.7 %TypedArray%.prototype.entries ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, key+value)。

23.2.3.8 %TypedArray%.prototype.every ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.6 中定义的 Array.prototype.every 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 testResultfalse,返回 false
    5. 设置 kk + 1。
  7. 返回 true

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.9 %TypedArray%.prototype.fill ( value [ , start [ , end ] ] )

该方法的参数解释和用法与 23.1.3.7 中定义的 Array.prototype.fill 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 O.[[ContentType]]bigint,将 value 设为 ? ToBigInt(value)。
  5. 否则,将 value 设为 ? ToNumber(value)。
  6. relativeStart 为 ? ToIntegerOrInfinity(start)。
  7. 如果 relativeStart = -∞,令 startIndex 为 0。
  8. 否则如果 relativeStart < 0,令 startIndexmax(len + relativeStart, 0)。
  9. 否则,令 startIndexmin(relativeStart, len)。
  10. 如果 endundefined,令 relativeEndlen;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  11. 如果 relativeEnd = -∞,令 endIndex 为 0。
  12. 否则如果 relativeEnd < 0,令 endIndexmax(len + relativeEnd, 0)。
  13. 否则,令 endIndexmin(relativeEnd, len)。
  14. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  15. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  16. 设置 lenTypedArrayLength(taRecord)。
  17. 设置 endIndexmin(endIndex, len)。
  18. kstartIndex
  19. 重复,直到 k < endIndex
    1. Pk 为 ! ToString(𝔽(k))。
    2. 执行 ! Set(O, Pk, value, true)。
    3. 设置 kk + 1。
  20. 返回 O

23.2.3.10 %TypedArray%.prototype.filter ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.8 中定义的 Array.prototype.filter 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. kept 为一个新的空 List
  6. captured 为 0。
  7. k 为 0。
  8. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. selectedToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 selectedtrue,则
      1. kValue 添加到 kept
      2. 设置 capturedcaptured + 1。
    5. 设置 kk + 1。
  9. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(captured) »)。
  10. n 为 0。
  11. 对于 kept 的每个元素 e,执行
    1. 执行 ! Set(A, ! ToString(𝔽(n)), e, true)。
    2. 设置 nn + 1。
  12. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.11 %TypedArray%.prototype.find ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.9 中定义的 Array.prototype.find 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.12 %TypedArray%.prototype.findIndex ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.10 中定义的 Array.prototype.findIndex 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, ascending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.13 %TypedArray%.prototype.findLast ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.11 中定义的 Array.prototype.findLast 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Value]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.14 %TypedArray%.prototype.findLastIndex ( predicate [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.12 中定义的 Array.prototype.findLastIndex 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. findRec 为 ? FindViaPredicate(O, len, descending, predicate, thisArg)。
  5. 返回 findRec.[[Index]]

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.15 %TypedArray%.prototype.forEach ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.15 中定义的 Array.prototype.forEach 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. 执行 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  7. 返回 undefined

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.16 %TypedArray%.prototype.includes ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.16 中定义的 Array.prototype.includes 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 false
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 false
  8. 否则如果 n = -∞,设置 n 为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  11. 重复,直到 k < len
    1. elementK 为 ! Get(O, ! ToString(𝔽(k)))。
    2. 如果 SameValueZero(searchElement, elementK) 为 true,返回 true
    3. 设置 kk + 1。
  12. 返回 false

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.17 %TypedArray%.prototype.indexOf ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.17 中定义的 Array.prototype.indexOf 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. n 为 ? ToIntegerOrInfinity(fromIndex)。
  6. 断言:如果 fromIndexundefined,则 n 为 0。
  7. 如果 n = +∞,返回 -1𝔽
  8. 否则如果 n = -∞,设置 n 为 0。
  9. 如果 n ≥ 0,则
    1. kn
  10. 否则,
    1. klen + n
    2. 如果 k < 0,设置 k 为 0。
  11. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk + 1。
  12. 返回 -1𝔽

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.18 %TypedArray%.prototype.join ( separator )

该方法的参数解释和用法与 23.1.3.18 中定义的 Array.prototype.join 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 separatorundefined,令 sep","
  5. 否则,令 sep 为 ? ToString(separator)。
  6. R 为空字符串。
  7. k 为 0。
  8. 重复,直到 k < len
    1. 如果 k > 0,令 R字符串拼接 Rsep 的结果。
    2. element 为 ! Get(O, ! ToString(𝔽(k)))。
    3. 如果 element 不为 undefined,则
      1. S 为 ! ToString(element)。
      2. R字符串拼接 RS 的结果。
    4. 设置 kk + 1。
  9. 返回 R

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.19 %TypedArray%.prototype.keys ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, key)。

23.2.3.20 %TypedArray%.prototype.lastIndexOf ( searchElement [ , fromIndex ] )

该方法的参数解释和用法与 23.1.3.20 中定义的 Array.prototype.lastIndexOf 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 len = 0,返回 -1𝔽
  5. 如果 fromIndex 被传入,令 n 为 ? ToIntegerOrInfinity(fromIndex);否则令 nlen - 1。
  6. 如果 n = -∞,返回 -1𝔽
  7. 如果 n ≥ 0,则
    1. kmin(n, len - 1)。
  8. 否则,
    1. klen + n
  9. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kPresent 为 ! HasProperty(O, Pk)。
    3. 如果 kPresenttrue,则
      1. elementK 为 ! Get(O, Pk)。
      2. 如果 IsStrictlyEqual(searchElement, elementK) 为 true,返回 𝔽(k)。
    4. 设置 kk - 1。
  10. 返回 -1𝔽

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.21 get %TypedArray%.prototype.length

%TypedArray%.prototype.length 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]][[ArrayLength]] 内部槽。
  4. taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  5. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,返回 +0𝔽
  6. lengthTypedArrayLength(taRecord)。
  7. 返回 𝔽(length)。

该函数不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.22 %TypedArray%.prototype.map ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.21 中定义的 Array.prototype.map 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(len) »)。
  6. k 为 0。
  7. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. mappedValue 为 ? Call(callback, thisArg, « kValue, 𝔽(k), O »)。
    4. 执行 ? Set(A, Pk, mappedValue, true)。
    5. 设置 kk + 1。
  8. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.23 %TypedArray%.prototype.reduce ( callback [ , initialValue ] )

该方法的参数解释和用法与 23.1.3.24 中定义的 Array.prototype.reduce 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. 如果 len = 0 且未传入 initialValue,抛出 TypeError 异常。
  6. k 为 0。
  7. accumulatorundefined
  8. 如果 initialValue 被传入,则
    1. accumulator 设为 initialValue
  9. 否则,
    1. Pk 为 ! ToString(𝔽(k))。
    2. accumulator 设为 ! Get(O, Pk)。
    3. 设置 kk + 1。
  10. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. accumulator 设为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk + 1。
  11. 返回 accumulator

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.24 %TypedArray%.prototype.reduceRight ( callback [ , initialValue ] )

该方法的参数解释和用法与 23.1.3.25 中定义的 Array.prototype.reduceRight 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. 如果 len = 0 且未传入 initialValue,抛出 TypeError 异常。
  6. klen - 1。
  7. accumulatorundefined
  8. 如果 initialValue 被传入,则
    1. accumulator 设为 initialValue
  9. 否则,
    1. Pk 为 ! ToString(𝔽(k))。
    2. accumulator 设为 ! Get(O, Pk)。
    3. 设置 kk - 1。
  10. 重复,直到 k ≥ 0,
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. accumulator 设为 ? Call(callback, undefined, « accumulator, kValue, 𝔽(k), O »)。
    4. 设置 kk - 1。
  11. 返回 accumulator

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.25 %TypedArray%.prototype.reverse ( )

该方法的参数解释和用法与 23.1.3.26 中定义的 Array.prototype.reverse 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. middlefloor(len / 2)。
  5. lower 为 0。
  6. 重复,直到 lowermiddle
    1. upperlen - lower - 1。
    2. upperP 为 ! ToString(𝔽(upper))。
    3. lowerP 为 ! ToString(𝔽(lower))。
    4. lowerValue 为 ! Get(O, lowerP)。
    5. upperValue 为 ! Get(O, upperP)。
    6. 执行 ! Set(O, lowerP, upperValue, true)。
    7. 执行 ! Set(O, upperP, lowerValue, true)。
    8. 设置 lowerlower + 1。
  7. 返回 O

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26 %TypedArray%.prototype.set ( source [ , offset ] )

该方法会在此 TypedArray 中设置多个值,从 source 读取值。具体细节取决于 source 的类型。可选的 offset 值表示在此 TypedArray 中写入值的第一个元素索引。如果省略,假定为 0。

该方法被调用时执行以下步骤:

  1. targetthis 值。
  2. 执行 ? RequireInternalSlot(target, [[TypedArrayName]])。
  3. 断言target 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. targetOffset 为 ? ToIntegerOrInfinity(offset)。
  5. 如果 targetOffset < 0,抛出 RangeError 异常。
  6. 如果 source 是带有 [[TypedArrayName]] 内部槽的 对象,则
    1. 执行 ? SetTypedArrayFromTypedArray(target, targetOffset, source)。
  7. 否则,
    1. 执行 ? SetTypedArrayFromArrayLike(target, targetOffset, source)。
  8. 返回 undefined

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.26.1 SetTypedArrayFromTypedArray ( target, targetOffset, source )

抽象操作 SetTypedArrayFromTypedArray 接收参数 target(一个 TypedArray)、targetOffset(一个非负 整数或 +∞)、source(一个 TypedArray),并返回 正常完成,包含 unused抛出完成。它会在 target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:

  1. targetBuffertarget.[[ViewedArrayBuffer]]
  2. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  3. 如果 IsTypedArrayOutOfBounds(targetRecord) 为 true,抛出 TypeError 异常。
  4. targetLengthTypedArrayLength(targetRecord)。
  5. srcBuffersource.[[ViewedArrayBuffer]]
  6. srcRecordMakeTypedArrayWithBufferWitnessRecord(source, seq-cst)。
  7. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,抛出 TypeError 异常。
  8. srcLengthTypedArrayLength(srcRecord)。
  9. targetTypeTypedArrayElementType(target)。
  10. targetElementSizeTypedArrayElementSize(target)。
  11. targetByteOffsettarget.[[ByteOffset]]
  12. srcTypeTypedArrayElementType(source)。
  13. srcElementSizeTypedArrayElementSize(source)。
  14. srcByteOffsetsource.[[ByteOffset]]
  15. 如果 targetOffset = +∞,抛出 RangeError 异常。
  16. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  17. 如果 target.[[ContentType]] 不等于 source.[[ContentType]],抛出 TypeError 异常。
  18. 如果 IsSharedArrayBuffer(srcBuffer) 为 trueIsSharedArrayBuffer(targetBuffer) 为 true,并且 srcBuffer.[[ArrayBufferData]] 等于 targetBuffer.[[ArrayBufferData]],则令 sameSharedArrayBuffertrue;否则,令 sameSharedArrayBufferfalse
  19. 如果 SameValue(srcBuffer, targetBuffer) 为 truesameSharedArrayBuffertrue,则
    1. srcByteLengthTypedArrayByteLength(srcRecord)。
    2. srcBuffer 设为 ? CloneArrayBuffer(srcBuffer, srcByteOffset, srcByteLength)。
    3. srcByteIndex 为 0。
  20. 否则,
    1. srcByteIndexsrcByteOffset
  21. targetByteIndex 为 (targetOffset × targetElementSize) + targetByteOffset
  22. limittargetByteIndex + (targetElementSize × srcLength)。
  23. 如果 srcType 等于 targetType,则
    1. 注:传输操作必须以保持源数据比特级编码的方式执行。
    2. 重复,直到 targetByteIndex < limit
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + 1。
      4. 设置 targetByteIndextargetByteIndex + 1。
  24. 否则,
    1. 重复,直到 targetByteIndex < limit
      1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, targetType, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + srcElementSize
      4. 设置 targetByteIndextargetByteIndex + targetElementSize
  25. 返回 unused

23.2.3.26.2 SetTypedArrayFromArrayLike ( target, targetOffset, source )

抽象操作 SetTypedArrayFromArrayLike 接收参数 target(一个 TypedArray)、targetOffset(一个非负 整数或 +∞)、source(一个 ECMAScript 语言值,但不是 TypedArray),并返回 正常完成,包含 unused抛出完成。它会在 target 从索引 targetOffset 开始,读取 source 的值设置多个值。调用时执行以下步骤:

  1. targetRecordMakeTypedArrayWithBufferWitnessRecord(target, seq-cst)。
  2. 如果 IsTypedArrayOutOfBounds(targetRecord) 为 true,抛出 TypeError 异常。
  3. targetLengthTypedArrayLength(targetRecord)。
  4. src 为 ? ToObject(source)。
  5. srcLength 为 ? LengthOfArrayLike(src)。
  6. 如果 targetOffset = +∞,抛出 RangeError 异常。
  7. 如果 srcLength + targetOffset > targetLength,抛出 RangeError 异常。
  8. k 为 0。
  9. 重复,直到 k < srcLength
    1. Pk 为 ! ToString(𝔽(k))。
    2. value 为 ? Get(src, Pk)。
    3. targetIndex𝔽(targetOffset + k)。
    4. 执行 ? TypedArraySetElement(target, targetIndex, value)。
    5. 设置 kk + 1。
  10. 返回 unused

23.2.3.27 %TypedArray%.prototype.slice ( start, end )

该方法的参数解释和用法与 23.1.3.28 中定义的 Array.prototype.slice 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. srcArrayLengthTypedArrayLength(taRecord)。
  4. relativeStart 为 ? ToIntegerOrInfinity(start)。
  5. 如果 relativeStart = -∞,令 startIndex 为 0。
  6. 否则如果 relativeStart < 0,令 startIndexmax(srcArrayLength + relativeStart, 0)。
  7. 否则,令 startIndexmin(relativeStart, srcArrayLength)。
  8. 如果 endundefined,令 relativeEndsrcArrayLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
  9. 如果 relativeEnd = -∞,令 endIndex 为 0。
  10. 否则如果 relativeEnd < 0,令 endIndexmax(srcArrayLength + relativeEnd, 0)。
  11. 否则,令 endIndexmin(relativeEnd, srcArrayLength)。
  12. countBytesmax(endIndex - startIndex, 0)。
  13. A 为 ? TypedArraySpeciesCreate(O, « 𝔽(countBytes) »)。
  14. 如果 countBytes > 0,则
    1. 设置 taRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
    2. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    3. 设置 endIndexmin(endIndex, TypedArrayLength(taRecord))。
    4. 设置 countBytesmax(endIndex - startIndex, 0)。
    5. srcTypeTypedArrayElementType(O)。
    6. targetTypeTypedArrayElementType(A)。
    7. 如果 srcType 等于 targetType,则
      1. 注:传输操作必须以保持源数据比特级编码的方式执行。
      2. srcBufferO.[[ViewedArrayBuffer]]
      3. targetBufferA.[[ViewedArrayBuffer]]
      4. elementSizeTypedArrayElementSize(O)。
      5. srcByteOffsetO.[[ByteOffset]]
      6. srcByteIndex 为 (startIndex × elementSize) + srcByteOffset
      7. targetByteIndexA.[[ByteOffset]]
      8. endByteIndextargetByteIndex + (countBytes × elementSize)。
      9. 重复,直到 targetByteIndex < endByteIndex
        1. valueGetValueFromBuffer(srcBuffer, srcByteIndex, uint8, true, unordered)。
        2. 执行 SetValueInBuffer(targetBuffer, targetByteIndex, uint8, value, true, unordered)。
        3. 设置 srcByteIndexsrcByteIndex + 1。
        4. 设置 targetByteIndextargetByteIndex + 1。
    8. 否则,
      1. n 为 0。
      2. kstartIndex
      3. 重复,直到 k < endIndex
        1. Pk 为 ! ToString(𝔽(k))。
        2. kValue 为 ! Get(O, Pk)。
        3. 执行 ! Set(A, ! ToString(𝔽(n)), kValue, true)。
        4. 设置 kk + 1。
        5. 设置 nn + 1。
  15. 返回 A

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.28 %TypedArray%.prototype.some ( callback [ , thisArg ] )

该方法的参数解释和用法与 23.1.3.29 中定义的 Array.prototype.some 相同。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  5. k 为 0。
  6. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. kValue 为 ! Get(O, Pk)。
    3. testResultToBoolean(? Call(callback, thisArg, « kValue, 𝔽(k), O »))。
    4. 如果 testResulttrue,返回 true
    5. 设置 kk + 1。
  7. 返回 false

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.29 %TypedArray%.prototype.sort ( comparator )

这是一个不同的方法,除下述说明外,其实现要求与 23.1.3.30 中定义的 Array.prototype.sort 相同。该方法的实现可以利用 this 值是一个具有固定长度且其 整数索引属性不是稀疏的对象这一事实进行优化。

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

该方法被调用时执行以下步骤:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. objthis 值。
  3. taRecord 为 ? ValidateTypedArray(obj, seq-cst)。
  4. lenTypedArrayLength(taRecord)。
  5. 注:以下闭包执行数值比较,而不是 23.1.3.30 中使用的字符串比较。
  6. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  7. sortedList 为 ? SortIndexedProperties(obj, len, SortCompare, read-through-holes)。
  8. j 为 0。
  9. 重复,直到 j < len
    1. 执行 ! Set(obj, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  10. 返回 obj

由于 NaN 总是大于任何其他值(见 CompareTypedArrayElements),当 comparator 未提供时,NaN 属性值总是排在结果的末尾。

23.2.3.30 %TypedArray%.prototype.subarray ( start, end )

该方法返回一个新的 TypedArray,其元素类型与此 TypedArray 的元素类型相同,ArrayBuffer 也与此 TypedArray 相同,引用 start(包含)到 end(不包含)区间内的元素。如果 startend 为负数,则它表示从数组末尾开始的索引,而不是从头开始。

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  3. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  4. bufferO.[[ViewedArrayBuffer]]
  5. srcRecordMakeTypedArrayWithBufferWitnessRecord(O, seq-cst)。
  6. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,则
    1. srcLength 为 0。
  7. 否则,
    1. srcLengthTypedArrayLength(srcRecord)。
  8. relativeStart 为 ? ToIntegerOrInfinity(start)。
  9. 如果 relativeStart = -∞,令 startIndex 为 0。
  10. 否则如果 relativeStart < 0,令 startIndexmax(srcLength + relativeStart, 0)。
  11. 否则,令 startIndexmin(relativeStart, srcLength)。
  12. elementSizeTypedArrayElementSize(O)。
  13. srcByteOffsetO.[[ByteOffset]]
  14. beginByteOffsetsrcByteOffset + (startIndex × elementSize)。
  15. 如果 O.[[ArrayLength]]autoendundefined,则
    1. argumentsList 为 « buffer, 𝔽(beginByteOffset) »。
  16. 否则,
    1. 如果 endundefined,令 relativeEndsrcLength;否则令 relativeEnd 为 ? ToIntegerOrInfinity(end)。
    2. 如果 relativeEnd = -∞,令 endIndex 为 0。
    3. 否则如果 relativeEnd < 0,令 endIndexmax(srcLength + relativeEnd, 0)。
    4. 否则,令 endIndexmin(relativeEnd, srcLength)。
    5. newLengthmax(endIndex - startIndex, 0)。
    6. argumentsList 为 « buffer, 𝔽(beginByteOffset), 𝔽(newLength) »。
  17. 返回 ? TypedArraySpeciesCreate(O, argumentsList)。

该方法不是泛型的。this 值必须是带有 [[TypedArrayName]] 内部槽的对象。

23.2.3.31 %TypedArray%.prototype.toLocaleString ( [ reserved1 [ , reserved2 ] ] )

这是一个不同的方法,其实现算法与 23.1.3.32 中定义的 Array.prototype.toLocaleString 相同,只是用 TypedArrayLength 替换了对 "length"[[Get]] 操作。该算法的实现可以利用 this 值在底层缓冲区不可调整大小时具有固定长度且其 整数索引属性不是稀疏的事实进行优化。但这种优化不能引入任何可观察的行为变化。

该方法不是泛型的。调用算法前会用 this 值和 seq-cst 作为参数调用 ValidateTypedArray。如果其结果是 异常完成,则抛出该异常而不是执行算法。

如果 ECMAScript 实现包含 ECMA-402 国际化 API,则该方法基于 ECMA-402 规范中的 Array.prototype.toLocaleString 算法。

23.2.3.32 %TypedArray%.prototype.toReversed ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lengthTypedArrayLength(taRecord)。
  4. A 为 ? TypedArrayCreateSameType(O, « 𝔽(length) »)。
  5. k 为 0。
  6. 重复,直到 k < length
    1. from 为 ! ToString(𝔽(length - k - 1))。
    2. Pk 为 ! ToString(𝔽(k))。
    3. fromValue 为 ! Get(O, from)。
    4. 执行 ! Set(A, Pk, fromValue, true)。
    5. 设置 kk + 1。
  7. 返回 A

23.2.3.33 %TypedArray%.prototype.toSorted ( comparator )

该方法被调用时执行以下步骤:

  1. 如果 comparator 不为 undefinedIsCallable(comparator) 为 false,抛出 TypeError 异常。
  2. Othis 值。
  3. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  4. lenTypedArrayLength(taRecord)。
  5. A 为 ? TypedArrayCreateSameType(O, « 𝔽(len) »)。
  6. 注:以下闭包执行数值比较,而不是 23.1.3.34 中使用的字符串比较。
  7. SortCompare 为一个新的 抽象闭包,带参数 (x, y),捕获 comparator 并在调用时执行以下步骤:
    1. 返回 ? CompareTypedArrayElements(x, y, comparator)。
  8. sortedList 为 ? SortIndexedProperties(O, len, SortCompare, read-through-holes)。
  9. j 为 0。
  10. 重复,直到 j < len
    1. 执行 ! Set(A, ! ToString(𝔽(j)), sortedList[j], true)。
    2. 设置 jj + 1。
  11. 返回 A

23.2.3.34 %TypedArray%.prototype.toString ( )

"toString" 属性的初始值是 %Array.prototype.toString%,定义见 23.1.3.36

23.2.3.35 %TypedArray%.prototype.values ( )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? ValidateTypedArray(O, seq-cst)。
  3. 返回 CreateArrayIterator(O, value)。

23.2.3.36 %TypedArray%.prototype.with ( index, value )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. taRecord 为 ? ValidateTypedArray(O, seq-cst)。
  3. lenTypedArrayLength(taRecord)。
  4. relativeIndex 为 ? ToIntegerOrInfinity(index)。
  5. 如果 relativeIndex ≥ 0,令 actualIndexrelativeIndex
  6. 否则,令 actualIndexlen + relativeIndex
  7. 如果 O.[[ContentType]]bigint,令 numericValue 为 ? ToBigInt(value)。
  8. 否则,令 numericValue 为 ? ToNumber(value)。
  9. 如果 IsValidIntegerIndex(O, 𝔽(actualIndex)) 为 false,抛出 RangeError 异常。
  10. A 为 ? TypedArrayCreateSameType(O, « 𝔽(len) »)。
  11. k 为 0。
  12. 重复,直到 k < len
    1. Pk 为 ! ToString(𝔽(k))。
    2. 如果 k = actualIndex,令 fromValuenumericValue
    3. 否则,令 fromValue 为 ! Get(O, Pk)。
    4. 执行 ! Set(A, Pk, fromValue, true)。
    5. 设置 kk + 1。
  13. 返回 A

23.2.3.37 %TypedArray%.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值是 %TypedArray.prototype.values%,定义见 23.2.3.35

23.2.3.38 get %TypedArray%.prototype [ %Symbol.toStringTag% ]

%TypedArray%.prototype[%Symbol.toStringTag%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Othis 值。
  2. 如果 O 不是对象,返回 undefined
  3. 如果 O 没有 [[TypedArrayName]] 内部槽,返回 undefined
  4. nameO.[[TypedArrayName]]
  5. 断言name 是字符串
  6. 返回 name

该属性具有属性 { [[Enumerable]]: false, [[Configurable]]: true }。

该函数的 "name" 属性的初始值为 "get [Symbol.toStringTag]"

23.2.4 TypedArray 对象的抽象操作

23.2.4.1 TypedArraySpeciesCreate ( exemplar, argumentList )

抽象操作 TypedArraySpeciesCreate 接收参数 exemplar(一个 TypedArray)和 argumentList(一个 List,元素为 ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用从 exemplar 派生的 构造函数 创建新的 TypedArray。与 ArraySpeciesCreate 可以通过 %Symbol.species% 创建非数组对象不同,此操作强制要求该 构造函数 必须创建实际的 TypedArray。调用时执行以下步骤:

  1. defaultConstructor表 75 中与 exemplar.[[TypedArrayName]] 同名的内建对象。
  2. constructor 为 ? SpeciesConstructor(exemplar, defaultConstructor)。
  3. result 为 ? TypedArrayCreateFromConstructor(constructor, argumentList)。
  4. 断言result 拥有 [[TypedArrayName]][[ContentType]] 内部槽。
  5. 如果 result.[[ContentType]] 不等于 exemplar.[[ContentType]],抛出 TypeError 异常。
  6. 返回 result

23.2.4.2 TypedArrayCreateFromConstructor ( constructor, argumentList )

抽象操作 TypedArrayCreateFromConstructor 接收参数 constructor(一个 构造函数)和 argumentList(一个 List,元素为ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用 构造函数 创建新的 TypedArray。调用时执行以下步骤:

  1. newTypedArray 为 ? Construct(constructor, argumentList)。
  2. taRecord 为 ? ValidateTypedArray(newTypedArray, seq-cst)。
  3. 如果 argumentList 的元素数量为 1 且 argumentList[0] 是数字,则
    1. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
    2. lengthTypedArrayLength(taRecord)。
    3. 如果 length < (argumentList[0]),抛出 TypeError 异常。
  4. 返回 newTypedArray

23.2.4.3 TypedArrayCreateSameType ( exemplar, argumentList )

抽象操作 TypedArrayCreateSameType 接收参数 exemplar(一个 TypedArray)和 argumentList(一个 List,元素为ECMAScript 语言值),返回 正常完成,包含一个 TypedArray抛出完成。它用于指定用从 exemplar 派生的 构造函数 创建新的 TypedArray。与 TypedArraySpeciesCreate 能通过 %Symbol.species% 构造自定义 TypedArray 子类不同,此操作始终使用内建 TypedArray 构造函数。调用时执行以下步骤:

  1. constructor表 75 中与 exemplar.[[TypedArrayName]] 同名的内建对象。
  2. result 为 ? TypedArrayCreateFromConstructor(constructor, argumentList)。
  3. 断言result 拥有 [[TypedArrayName]][[ContentType]] 内部槽。
  4. 断言result.[[ContentType]] 等于 exemplar.[[ContentType]]
  5. 返回 result

23.2.4.4 ValidateTypedArray ( O, order )

抽象操作 ValidateTypedArray 接收参数 O(一个 ECMAScript 语言值)和 orderseq-cstunordered),返回 正常完成,包含一个 TypedArray 带缓冲区见证记录抛出完成。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(O, [[TypedArrayName]])。
  2. 断言O 拥有 [[ViewedArrayBuffer]] 内部槽。
  3. taRecordMakeTypedArrayWithBufferWitnessRecord(O, order)。
  4. 如果 IsTypedArrayOutOfBounds(taRecord) 为 true,抛出 TypeError 异常。
  5. 返回 taRecord

23.2.4.5 TypedArrayElementSize ( O )

抽象操作 TypedArrayElementSize 接收参数 O(一个 TypedArray),返回一个非负整数。调用时执行以下步骤:

  1. 返回 表 75O.[[TypedArrayName]] 指定的元素大小值。

23.2.4.6 TypedArrayElementType ( O )

抽象操作 TypedArrayElementType 接收参数 O(一个 TypedArray),返回 TypedArray 元素类型。调用时执行以下步骤:

  1. 返回 表 75O.[[TypedArrayName]] 指定的元素类型值。

23.2.4.7 CompareTypedArrayElements ( x, y, comparator )

抽象操作 CompareTypedArrayElements 接收参数 x(一个 Number 或 BigInt)、y(一个 Number 或 BigInt)、comparator(一个 函数对象undefined),返回 正常完成,包含一个 Number 或 异常完成。调用时执行以下步骤:

  1. 断言x 是 Numbery 是 Number,或者 x 是 BigInty 是 BigInt
  2. 如果 comparator 不为 undefined,则
    1. v 为 ? ToNumber(? Call(comparator, undefined, « x, y »))。
    2. 如果 vNaN,返回 +0𝔽
    3. 返回 v
  3. 如果 xy 都是 NaN,返回 +0𝔽
  4. 如果 xNaN,返回 1𝔽
  5. 如果 yNaN,返回 -1𝔽
  6. 如果 x < y,返回 -1𝔽
  7. 如果 x > y,返回 1𝔽
  8. 如果 x-0𝔽y+0𝔽,返回 -1𝔽
  9. 如果 x+0𝔽y-0𝔽,返回 1𝔽
  10. 返回 +0𝔽
这执行的是数值比较,而不是 23.1.3.30.2 中的字符串比较。

23.2.5 TypedArray 构造函数

每个 TypedArray 构造函数

  • 是一个内建对象,结构如下所述,唯一的区别是 构造函数 名称不同于 TypedArray,见 表 75
  • 是一个函数,其行为会根据参数的数量和类型而异。对 TypedArray 的实际调用行为取决于传递给它的参数数量和类型。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 TypedArray 行为的子类 构造函数 必须包含对 TypedArray 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 %TypedArray%.prototype 内建方法。

23.2.5.1 TypedArray ( ...args )

每个 TypedArray 构造函数 被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. constructorName表 75 中为此 TypedArray 构造函数 指定的 构造函数 名称的字符串值。
  3. proto"%TypedArray.prototype%"
  4. numberOfArgsargs 的元素数量。
  5. 如果 numberOfArgs = 0,则
    1. 返回 ? AllocateTypedArray(constructorName, NewTarget, proto, 0)。
  6. 否则,
    1. firstArgumentargs[0]。
    2. 如果 firstArgument 是对象,则
      1. O 为 ? AllocateTypedArray(constructorName, NewTarget, proto)。
      2. 如果 firstArgument[[TypedArrayName]] 内部槽,则
        1. 执行 ? InitializeTypedArrayFromTypedArray(O, firstArgument)。
      3. 否则如果 firstArgument[[ArrayBufferData]] 内部槽,则
        1. 如果 numberOfArgs > 1,令 byteOffsetargs[1];否则令 byteOffsetundefined
        2. 如果 numberOfArgs > 2,令 lengthargs[2];否则令 lengthundefined
        3. 执行 ? InitializeTypedArrayFromArrayBuffer(O, firstArgument, byteOffset, length)。
      4. 否则,
        1. 断言firstArgument 是对象firstArgument 没有 [[TypedArrayName]][[ArrayBufferData]] 内部槽。
        2. usingIterator 为 ? GetMethod(firstArgument, %Symbol.iterator%)。
        3. 如果 usingIterator 不为 undefined,则
          1. values 为 ? IteratorToList(? GetIteratorFromMethod(firstArgument, usingIterator))。
          2. 执行 ? InitializeTypedArrayFromList(O, values)。
        4. 否则,
          1. 注:firstArgument 不是 可迭代对象,所以假定它已经是 类数组对象
          2. 执行 ? InitializeTypedArrayFromArrayLike(O, firstArgument)。
      5. 返回 O
    3. 否则,
      1. 断言firstArgument 不是对象
      2. elementLength 为 ? ToIndex(firstArgument)。
      3. 返回 ? AllocateTypedArray(constructorName, NewTarget, proto, elementLength)。

23.2.5.1.1 AllocateTypedArray ( constructorName, newTarget, defaultProto [ , length ] )

抽象操作 AllocateTypedArray 接收参数 constructorName(一个字符串,为 TypedArray 构造函数名称,见 表 75),newTarget(一个 构造函数),defaultProto(一个字符串),可选参数 length(一个非负整数),返回 正常完成,包含一个 TypedArray抛出完成。用于校验并创建 TypedArray 构造函数 的实例。如果传入了 length,还会分配一个相应长度的 ArrayBuffer,并与新的 TypedArray 实例关联。AllocateTypedArray 提供了 TypedArray 共享的通用语义。调用时执行以下步骤:

  1. proto 为 ? GetPrototypeFromConstructor(newTarget, defaultProto)。
  2. objTypedArrayCreate(proto)。
  3. 断言obj.[[ViewedArrayBuffer]]undefined
  4. 设置 obj.[[TypedArrayName]]constructorName
  5. 如果 constructorName"BigInt64Array""BigUint64Array",将 obj.[[ContentType]] 设为 bigint
  6. 否则,将 obj.[[ContentType]] 设为 number
  7. 如果未传入 length,则
    1. 设置 obj.[[ByteLength]] 为 0。
    2. 设置 obj.[[ByteOffset]] 为 0。
    3. 设置 obj.[[ArrayLength]] 为 0。
  8. 否则,
    1. 执行 ? AllocateTypedArrayBuffer(obj, length)。
  9. 返回 obj

23.2.5.1.2 InitializeTypedArrayFromTypedArray ( O, srcArray )

抽象操作 InitializeTypedArrayFromTypedArray 接收参数 O(一个 TypedArray)和 srcArray(一个 TypedArray),返回 正常完成,包含 unused抛出完成。调用时执行以下步骤:

  1. srcDatasrcArray.[[ViewedArrayBuffer]]
  2. elementTypeTypedArrayElementType(O)。
  3. elementSizeTypedArrayElementSize(O)。
  4. srcTypeTypedArrayElementType(srcArray)。
  5. srcElementSizeTypedArrayElementSize(srcArray)。
  6. srcByteOffsetsrcArray.[[ByteOffset]]
  7. srcRecordMakeTypedArrayWithBufferWitnessRecord(srcArray, seq-cst)。
  8. 如果 IsTypedArrayOutOfBounds(srcRecord) 为 true,抛出 TypeError 异常。
  9. elementLengthTypedArrayLength(srcRecord)。
  10. byteLengthelementSize × elementLength
  11. 如果 elementType 等于 srcType,则
    1. data 为 ? CloneArrayBuffer(srcData, srcByteOffset, byteLength)。
  12. 否则,
    1. data 为 ? AllocateArrayBuffer(%ArrayBuffer%, byteLength)。
    2. 如果 srcArray.[[ContentType]] 不等于 O.[[ContentType]],抛出 TypeError 异常。
    3. srcByteIndexsrcByteOffset
    4. targetByteIndex 为 0。
    5. countelementLength
    6. 重复,直到 count > 0,
      1. valueGetValueFromBuffer(srcData, srcByteIndex, srcType, true, unordered)。
      2. 执行 SetValueInBuffer(data, targetByteIndex, elementType, value, true, unordered)。
      3. 设置 srcByteIndexsrcByteIndex + srcElementSize
      4. 设置 targetByteIndextargetByteIndex + elementSize
      5. 设置 countcount - 1。
  13. 设置 O.[[ViewedArrayBuffer]]data
  14. 设置 O.[[ByteLength]]byteLength
  15. 设置 O.[[ByteOffset]] 为 0。
  16. 设置 O.[[ArrayLength]]elementLength
  17. 返回 unused

23.2.6 TypedArray 构造函数的属性

每个 TypedArray 构造函数

  • 拥有一个 [[Prototype]] 内部槽,其值为 %TypedArray%
  • 有一个 "length" 属性,其值为 3𝔽
  • 有一个 "name" 属性,其值为 构造函数表 75 中为其指定的字符串值。
  • 拥有以下属性:

23.2.6.1 TypedArray.BYTES_PER_ELEMENT

TypedArray.BYTES_PER_ELEMENT 的值为 表 75 中为 TypedArray 指定的元素大小值。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.6.2 TypedArray.prototype

TypedArray.prototype 的初始值为对应的 TypedArray 原型内建对象(23.2.7)。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7 TypedArray 原型对象的属性

每个 TypedArray 原型对象:

  • 拥有一个 [[Prototype]] 内部槽,其值为 %TypedArray.prototype%
  • 是一个 普通对象
  • 没有 [[ViewedArrayBuffer]] 或其它 TypedArray 实例对象专有的内部槽。

23.2.7.1 TypedArray.prototype.BYTES_PER_ELEMENT

TypedArray.prototype.BYTES_PER_ELEMENT 的值为 表 75 中为 TypedArray 指定的元素大小值。

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

23.2.7.2 TypedArray.prototype.constructor

某给定 TypedArray 构造函数的原型的 "constructor" 属性的初始值为该 构造函数 本身。

23.2.8 TypedArray 实例的属性

TypedArray 实例是 TypedArrays。每个 TypedArray 实例继承自对应的 TypedArray 原型对象。每个 TypedArray 实例都有如下内部槽:[[TypedArrayName]][[ViewedArrayBuffer]][[ByteLength]][[ByteOffset]][[ArrayLength]]

24 键控集合

24.1 Map 对象

Map 是一种键/值对集合,其中键和值都可以是任意的 ECMAScript 语言值。在 Map 的集合中,每个不同的键值只能出现在一个键/值对中。不同的键值通过 SameValueZero 比较算法进行区分。

Map 必须通过哈希表或其他机制实现,这些机制平均而言可以提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 Map 所需的可观察语义,而不是可行的实现模型。

24.1.1 Map 构造函数

Map 构造函数

  • %Map%
  • 全局对象"Map" 属性的初始值。
  • 作为 构造函数 调用时会创建并初始化一个新的 Map。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 Map 行为的子类 构造函数 必须包含对 Map 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 Map.prototype 内建方法。

24.1.1.1 Map ( [ iterable ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Map.prototype%", « [[MapData]] »)。
  3. 设置 map.[[MapData]] 为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 为 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。

如果参数 iterable 存在,期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个 迭代器对象,它会生成一个包含两个元素的 类数组对象,第一个元素将用作 Map 的键,第二个元素作为与该键关联的值。

24.1.1.2 AddEntriesFromIterable ( target, iterable, adder )

抽象操作 AddEntriesFromIterable 接收参数 target(一个对象)、iterableECMAScript 语言值,但不是 undefinednull)、adder(一个 函数对象),返回 正常完成,包含一个 ECMAScript 语言值抛出完成adder 调用时其接收者为 target。调用时执行以下步骤:

  1. iteratorRecord 为 ? GetIterator(iterable, sync)。
  2. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 target
    3. 如果 next 不是对象,则
      1. errorThrowCompletion(一个新创建的 TypeError 对象)。
      2. 返回 ? IteratorClose(iteratorRecord, error)。
    4. kCompletion(Get(next, "0"))。
    5. IfAbruptCloseIterator(k, iteratorRecord)。
    6. vCompletion(Get(next, "1"))。
    7. IfAbruptCloseIterator(v, iteratorRecord)。
    8. statusCompletion(Call(adder, target, « k, v »))。
    9. IfAbruptCloseIterator(status, iteratorRecord)。

参数 iterable 期望是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个 迭代器对象,它会生成一个包含两个元素的 类数组对象,第一个元素用作 Map 的键,第二个元素作为与该键关联的值。

24.1.2 Map 构造函数的属性

Map 构造函数

24.1.2.1 Map.groupBy ( items, callback )

callback 应该是一个接受两个参数的函数。groupBy 会按照升序对 items 中的每个元素调用 callback 一次,并构造一个新的 Map。每个 callback 返回的值会作为 Map 的键。对于每个这样的键,结果 Map 有一个键为该键、值为包含所有 callback 返回该键的元素的数组的条目。

callback 的两个参数分别是元素的值和索引。

groupBy 的返回值是一个 Map。

该函数被调用时执行以下步骤:

  1. groups 为 ? GroupBy(items, callback, collection)。
  2. map 为 ! Construct(%Map%)。
  3. 对于 groups 中的每个 Record { [[Key]], [[Elements]] } g,执行
    1. elementsCreateArrayFromList(g.[[Elements]])。
    2. entryRecord { [[Key]]: g.[[Key]], [[Value]]: elements }。
    3. entry 添加到 map.[[MapData]]
  4. 返回 map

24.1.2.2 Map.prototype

Map.prototype 的初始值为 Map 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.1.2.3 get Map [ %Symbol.species% ]

Map[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性的值为 "get [Symbol.species]"

创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的 构造函数。子类 构造函数 可以重写 %Symbol.species% 以更改默认的 构造函数 分配。

24.1.3 Map 原型对象的属性

Map 原型对象

  • %Map.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[MapData]] 内部槽。

24.1.3.1 Map.prototype.clear ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. p.[[Key]] 设为 empty
    2. p.[[Value]] 设为 empty
  4. 返回 undefined

现有的 [[MapData]] List 会被保留,因为可能存在正在遍历该 ListMap 迭代器对象

24.1.3.2 Map.prototype.constructor

Map.prototype.constructor 的初始值为 %Map%

24.1.3.3 Map.prototype.delete ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.1.3.4 Map.prototype.entries ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key+value)。

24.1.3.5 Map.prototype.forEach ( callback [ , thisArg ] )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. entriesM.[[MapData]]
  5. numEntriesentries 的元素个数。
  6. index 为 0。
  7. 重复,直到 index < numEntries
    1. eentries[index]。
    2. 设置 indexindex + 1。
    3. 如果 e.[[Key]] 不为 empty,则
      1. 执行 ? Call(callback, thisArg, « e.[[Value]], e.[[Key]], M »)。
      2. 注:在 callback 执行期间 entries 的元素数量可能增加。
      3. 设置 numEntriesentries 的当前元素数量。
  8. 返回 undefined

callback 应该是一个接受三个参数的函数。forEach 会按照键的插入顺序对 Map 中每个键/值对调用 callback 一次。只有实际存在的 Map 键才会被调用 callback;已被删除的键不会被调用。

如果提供了 thisArg 参数,则该参数会作为每次调用 callback 时的 this 值。如果未提供,则使用 undefined

callback 的三个参数分别是项的值、项的键,以及被遍历的 Map。

forEach 本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。map 的 [[MapData]] 的每个条目只会被访问一次。在 forEach 开始后添加的新键会被访问。如果某个键被访问后被删除并在 forEach 完成前重新添加,则该键会被再次访问。在 forEach 开始后但被访问前被删除的键不会被访问,除非该键在 forEach 完成前被再次添加。

24.1.3.6 Map.prototype.get ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.1.3.7 Map.prototype.has ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.1.3.8 Map.prototype.keys ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, key)。

24.1.3.9 Map.prototype.set ( key, value )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. key 设为 CanonicalizeKeyedCollectionKey(key)。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. pRecord { [[Key]]: key, [[Value]]: value }。
  6. p 添加到 M.[[MapData]]
  7. 返回 M

24.1.3.10 get Map.prototype.size

Map.prototype.size 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[MapData]])。
  3. count 为 0。
  4. 对于 M.[[MapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 empty,则将 count 设为 count + 1。
  5. 返回 𝔽(count)。

24.1.3.11 Map.prototype.values ( )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 返回 ? CreateMapIterator(M, value)。

24.1.3.12 Map.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Map.prototype.entries%,定义见 24.1.3.4

24.1.3.13 Map.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Map"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.1.4 Map 实例的属性

Map 实例是 普通对象,它们继承自 Map 原型的属性。Map 实例还拥有 [[MapData]] 内部槽。

24.1.5 Map 迭代器对象

Map 迭代器 是一个表示对某个特定 Map 实例对象的特定遍历的对象。Map 迭代器对象没有具名的 构造函数。相反,Map 迭代器对象是通过调用 Map 实例对象的某些方法创建的。

24.1.5.1 CreateMapIterator ( map, kind )

抽象操作 CreateMapIterator 接收参数 map(一个 ECMAScript 语言值)和 kindkey+valuekeyvalue),返回 正常完成,包含一个生成器,或 抛出完成。用于为返回此类 迭代器的 Map 方法创建 迭代器对象。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(map, [[MapData]])。
  2. closure 为一个新的 抽象闭包,无参数,捕获 mapkind,调用时执行以下步骤:
    1. entriesmap.[[MapData]]
    2. index 为 0。
    3. numEntriesentries 的元素数量。
    4. 重复,直到 index < numEntries
      1. eentries[index]。
      2. 设置 indexindex + 1。
      3. 如果 e.[[Key]] 不为 empty,则
        1. 如果 kindkey,则
          1. resulte.[[Key]]
        2. 否则如果 kindvalue,则
          1. resulte.[[Value]]
        3. 否则,
          1. 断言kindkey+value
          2. resultCreateArrayFromListe.[[Key]], e.[[Value]] »)。
        4. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        5. 注:在 GeneratorYield 挂起本抽象操作执行期间,entries 的元素数量可能增加。
        6. 设置 numEntriesentries 的元素数量。
    5. 返回 undefined
  3. 返回 CreateIteratorFromClosure(closure, "%MapIteratorPrototype%", %MapIteratorPrototype%)。

24.1.5.2 %MapIteratorPrototype% 对象

%MapIteratorPrototype% 对象:

24.1.5.2.1 %MapIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%MapIteratorPrototype%")。

24.1.5.2.2 %MapIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Map Iterator"

该属性具有特性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

24.2 Set 对象

Set 对象是 ECMAScript 语言值 的集合。在 Set 的集合中,每个不同的值只能出现一次。不同的值通过 SameValueZero 比较算法进行区分。

Set 对象必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 Set 对象所需的可观察语义,而非实际的实现模型。

24.2.1 Set 对象的抽象操作

24.2.1.1 Set 记录

Set 记录是一个 Record 值,用于封装 Set 或类似对象的接口。

Set 记录具有 表 76 中列出的字段。

表 76: Set 记录 字段
字段名 含义
[[SetObject]] 一个对象 该 Set 或类似对象。
[[Size]] 一个非负的 整数 或 +∞ 该对象报告的大小。
[[Has]] 一个 函数对象 该对象的 has 方法。
[[Keys]] 一个 函数对象 该对象的 keys 方法。

24.2.1.2 GetSetRecord ( obj )

抽象操作 GetSetRecord 接收参数 obj(一个 ECMAScript 语言值),返回 正常完成,包含一个 Set 记录抛出完成。调用时执行以下步骤:

  1. 如果 obj 不是对象,抛出 TypeError 异常。
  2. rawSize 为 ? Get(obj, "size")。
  3. numSize 为 ? ToNumber(rawSize)。
  4. 注:如果 rawSizeundefined,则 numSize 会是 NaN
  5. 如果 numSizeNaN,抛出 TypeError 异常。
  6. intSize 为 ! ToIntegerOrInfinity(numSize)。
  7. 如果 intSize < 0,抛出 RangeError 异常。
  8. has 为 ? Get(obj, "has")。
  9. 如果 IsCallable(has) 为 false,抛出 TypeError 异常。
  10. keys 为 ? Get(obj, "keys")。
  11. 如果 IsCallable(keys) 为 false,抛出 TypeError 异常。
  12. 返回一个新的 Set 记录 { [[SetObject]]: obj, [[Size]]: intSize, [[Has]]: has, [[Keys]]: keys }。

24.2.1.3 SetDataHas ( setData, value )

抽象操作 SetDataHas 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty)和 value(一个 ECMAScript 语言值),返回一个布尔值。调用时执行以下步骤:

  1. 如果 SetDataIndex(setData, value) 为 not-found,返回 false
  2. 返回 true

24.2.1.4 SetDataIndex ( setData, value )

抽象操作 SetDataIndex 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty)和 value(一个 ECMAScript 语言值),返回一个非负的 整数not-found。调用时执行以下步骤:

  1. value 设为 CanonicalizeKeyedCollectionKey(value)。
  2. sizesetData 的元素数量。
  3. index 为 0。
  4. 重复,直到 index < size
    1. esetData[index]。
    2. 如果 e 不为 emptye 等于 value,则
      1. 返回 index
    3. index 设为 index + 1。
  5. 返回 not-found

24.2.1.5 SetDataSize ( setData )

抽象操作 SetDataSize 接收参数 setData(一个 List,元素为 ECMAScript 语言值empty),返回一个非负 整数。调用时执行以下步骤:

  1. count 为 0。
  2. 对于 setData 的每个元素 e,执行
    1. 如果 e 不为 empty,将 count 设为 count + 1。
  3. 返回 count

24.2.2 Set 构造函数

Set 构造函数

  • %Set%
  • 全局对象"Set" 属性的初始值。
  • 作为 构造函数 调用时会创建并初始化一个新的 Set 对象。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 Set 行为的子类 构造函数 必须包含对 Set 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 Set.prototype 内建方法。

24.2.2.1 Set ( [ iterable ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%Set.prototype%", « [[SetData]] »)。
  3. 设置 set.[[SetData]] 为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 为 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.2.3 Set 构造函数的属性

Set 构造函数

24.2.3.1 Set.prototype

Set.prototype 的初始值为 Set 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.2.3.2 get Set [ %Symbol.species% ]

Set[%Symbol.species%] 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. 返回 this 值。

该函数的 "name" 属性值为 "get [Symbol.species]"

创建派生集合对象的方法应当调用 %Symbol.species% 以确定用于创建派生对象的 构造函数。子类 构造函数 可以重写 %Symbol.species% 以更改默认的 构造函数 分配。

24.2.4 Set 原型对象的属性

Set 原型对象

  • %Set.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[SetData]] 内部槽。

24.2.4.1 Set.prototype.add ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 添加到 S.[[SetData]]
  6. 返回 S

24.2.4.2 Set.prototype.clear ( )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. 对于 S.[[SetData]] 的每个元素 e,执行
    1. S.[[SetData]] 中值为 e 的元素替换为值为 empty 的元素。
  4. 返回 undefined

现有的 [[SetData]] List 会被保留,因为可能存在正在遍历该 ListSet 迭代器对象

24.2.4.3 Set.prototype.constructor

Set.prototype.constructor 的初始值为 %Set%

24.2.4.4 Set.prototype.delete ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]]).
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. S.[[SetData]] 中值为 e 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.2.4.5 Set.prototype.difference ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]]).
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetDataO.[[SetData]] 的一个副本。
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eresultSetData[index]。
      2. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,则
          1. resultSetData[index] 设为 empty
      3. index 设为 index + 1。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不为 done,则
        1. next 设为 CanonicalizeKeyedCollectionKey(next)。
        2. valueIndexSetDataIndex(resultSetData, next)。
        3. 如果 valueIndex 不为 not-found,则
          1. resultSetData[valueIndex] 设为 empty
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 设置 result.[[SetData]]resultSetData
  9. 返回 result

24.2.4.6 Set.prototype.entries ( )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 返回 ? CreateSetIterator(S, key+value)。

对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。

24.2.4.7 Set.prototype.forEach ( callback [ , thisArg ] )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. 如果 IsCallable(callback) 为 false,抛出 TypeError 异常。
  4. entriesS.[[SetData]]
  5. numEntriesentries 的元素数量。
  6. index 为 0。
  7. 重复,直到 index < numEntries
    1. eentries[index]。
    2. 设置 indexindex + 1。
    3. 如果 e 不为 empty,则
      1. 执行 ? Call(callback, thisArg, « e, e, S »)。
      2. 注:在 callback 执行期间 entries 的数量可能增加。
      3. 设置 numEntriesentries 的当前元素数量。
  8. 返回 undefined

callback 应该是一个接受三个参数的函数。forEach 会按照值插入顺序对 Set 对象中每个存在的值调用 callback 一次。只有实际存在的 Set 值才会被调用 callback;已被删除的键不会被调用。

如果提供了 thisArg 参数,则其会用作每次调用 callback 时的 this 值。如果未提供,则使用 undefined

callback 会被传入三个参数:前两个参数是 Set 中包含的同一个值,第三个参数是正在遍历的 Set 对象。

回调函数采用三个参数是为了与 Map 和 Array 的 forEach 方法的回调一致。对于 Set,每个元素既视为键又视为值。

forEach 本身不会直接修改被调用对象,但该对象可能会被 callback 的调用修改。

每个值通常只会被访问一次。不过,如果某个值被访问后被删除并在 forEach 完成前重新添加,则该值会被再次访问。在 forEach 开始后但被访问前被删除的值不会被访问,除非该值在 forEach 完成前被再次添加。在 forEach 开始后添加的新值会被访问。

24.2.4.8 Set.prototype.has ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. value 设为 CanonicalizeKeyedCollectionKey(value)。
  4. 对于 S.[[SetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.2.4.9 Set.prototype.intersection ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. resultSetData 为一个新的空 List
  5. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eO.[[SetData]][index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,则
          1. 注:较早对 otherRec.[[Has]] 的调用可能会移除并重新添加 O.[[SetData]] 的元素,这可能导致同一元素在本遍历中被访问两次。
          2. 如果 SetDataHas(resultSetData, e) 为 false,则
            1. e 添加到 resultSetData
        3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
        4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  6. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不为 done,则
        1. next 设为 CanonicalizeKeyedCollectionKey(next)。
        2. inThisSetDataHas(O.[[SetData]], next)。
        3. 如果 inThistrue,则
          1. 注:由于 other 是任意对象,其 "keys" 迭代器 可能会多次产出同一值。
          2. 如果 SetDataHas(resultSetData, next) 为 false,则
            1. next 添加到 resultSetData
  7. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  8. 设置 result.[[SetData]]resultSetData
  9. 返回 result

24.2.4.10 Set.prototype.isDisjointFrom ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) ≤ otherRec.[[Size]],则
    1. thisSizeO.[[SetData]] 的元素数量。
    2. index 为 0。
    3. 重复,直到 index < thisSize
      1. eO.[[SetData]][index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
        2. 如果 inOthertrue,返回 false
        3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
        4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  5. 否则,
    1. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
    2. nextnot-started
    3. 重复,直到 next 不为 done
      1. next 设为 ? IteratorStepValue(keysIter)。
      2. 如果 next 不为 done,则
        1. 如果 SetDataHas(O.[[SetData]], next) 为 true,则
          1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
          2. 返回 false
  6. 返回 true

24.2.4.11 Set.prototype.isSubsetOf ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) > otherRec.[[Size]],返回 false
  5. thisSizeO.[[SetData]] 的元素数量。
  6. index 为 0。
  7. 重复,直到 index < thisSize
    1. eO.[[SetData]][index]。
    2. 设置 indexindex + 1。
    3. 如果 e 不为 empty,则
      1. inOtherToBoolean(? Call(otherRec.[[Has]], otherRec.[[SetObject]], « e »))。
      2. 如果 inOtherfalse,返回 false
      3. 注:在 otherRec.[[Has]] 执行期间,O.[[SetData]] 的元素数量可能增加。
      4. 设置 thisSizeO.[[SetData]] 的当前元素数量。
  8. 返回 true

24.2.4.12 Set.prototype.isSupersetOf ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. 如果 SetDataSize(O.[[SetData]]) < otherRec.[[Size]],返回 false
  5. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不为 done,则
      1. 如果 SetDataHas(O.[[SetData]], next) 为 false,则
        1. 执行 ? IteratorClose(keysIter, NormalCompletion(unused))。
        2. 返回 false
  8. 返回 true

24.2.4.13 Set.prototype.keys ( )

"keys" 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

对于遍历目的,Set 类似于每个条目的键和值都相同的 Map。

24.2.4.14 get Set.prototype.size

Set.prototype.size 是一个 访问器属性,其 set 访问器函数为 undefined。其 get 访问器函数被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[SetData]])。
  3. sizeSetDataSize(S.[[SetData]])。
  4. 返回 𝔽(size)。

24.2.4.15 Set.prototype.symmetricDifference ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不为 done,则
      1. next 设为 CanonicalizeKeyedCollectionKey(next)。
      2. resultIndexSetDataIndex(resultSetData, next)。
      3. 如果 resultIndexnot-found,令 alreadyInResultfalse。否则令 alreadyInResulttrue
      4. 如果 SetDataHas(O.[[SetData]], next) 为 true,则
        1. 如果 alreadyInResulttrue,将 resultSetData[resultIndex] 设为 empty
      5. 否则,
        1. 如果 alreadyInResultfalse,将 next 添加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. 设置 result.[[SetData]]resultSetData
  10. 返回 result

24.2.4.16 Set.prototype.union ( other )

该方法被调用时执行以下步骤:

  1. Othis 值。
  2. 执行 ? RequireInternalSlot(O, [[SetData]])。
  3. otherRec 为 ? GetSetRecord(other)。
  4. keysIter 为 ? GetIteratorFromMethod(otherRec.[[SetObject]], otherRec.[[Keys]])。
  5. resultSetDataO.[[SetData]] 的一个副本。
  6. nextnot-started
  7. 重复,直到 next 不为 done
    1. next 设为 ? IteratorStepValue(keysIter)。
    2. 如果 next 不为 done,则
      1. next 设为 CanonicalizeKeyedCollectionKey(next)。
      2. 如果 SetDataHas(resultSetData, next) 为 false,则
        1. next 添加到 resultSetData
  8. resultOrdinaryObjectCreate(%Set.prototype%, « [[SetData]] »)。
  9. 设置 result.[[SetData]]resultSetData
  10. 返回 result

24.2.4.17 Set.prototype.values ( )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 返回 ? CreateSetIterator(S, value)。

24.2.4.18 Set.prototype [ %Symbol.iterator% ] ( )

%Symbol.iterator% 属性的初始值为 %Set.prototype.values%,定义见 24.2.4.17

24.2.4.19 Set.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Set"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.2.5 Set 实例的属性

Set 实例是 普通对象,它们继承自 Set 原型的属性。Set 实例还拥有 [[SetData]] 内部槽。

24.2.6 Set 迭代器对象

Set 迭代器 是一个 普通对象,结构如下定义,用于表示对某个特定 Set 实例对象的特定遍历。Set 迭代器对象没有具名的 构造函数。相反,Set 迭代器对象是通过调用 Set 实例对象的某些方法创建的。

24.2.6.1 CreateSetIterator ( set, kind )

抽象操作 CreateSetIterator 接收参数 set(一个 ECMAScript 语言值)和 kindkey+valuevalue),返回 正常完成,包含一个生成器,或 抛出完成。用于为返回此类 迭代器的 Set 方法创建 迭代器对象。调用时执行以下步骤:

  1. 执行 ? RequireInternalSlot(set, [[SetData]])。
  2. closure 为一个新的 抽象闭包,无参数,捕获 setkind,调用时执行以下步骤:
    1. index 为 0。
    2. entriesset.[[SetData]]
    3. numEntriesentries 的元素数量。
    4. 重复,直到 index < numEntries
      1. eentries[index]。
      2. 设置 indexindex + 1。
      3. 如果 e 不为 empty,则
        1. 如果 kindkey+value,则
          1. resultCreateArrayFromListe, e »)。
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(result, false))。
        2. 否则,
          1. 断言kindvalue
          2. 执行 ? GeneratorYield(CreateIteratorResultObject(e, false))。
        3. 注:在 GeneratorYield 挂起本抽象操作执行期间,entries 的元素数量可能增加。
        4. 设置 numEntriesentries 的当前元素数量。
    5. 返回 undefined
  3. 返回 CreateIteratorFromClosure(closure, "%SetIteratorPrototype%", %SetIteratorPrototype%)。

24.2.6.2 %SetIteratorPrototype% 对象

%SetIteratorPrototype% 对象:

24.2.6.2.1 %SetIteratorPrototype%.next ( )

  1. 返回 ? GeneratorResume(this 值, empty, "%SetIteratorPrototype%")。

24.2.6.2.2 %SetIteratorPrototype% [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "Set Iterator"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

24.3 WeakMap 对象

WeakMap 是键/值对的集合,其中键是对象和/或符号,值可以是任意的 ECMAScript 语言值。WeakMap 可以用来查询是否包含某个特定键的键/值对,但没有机制用于枚举它所持有的所有键。在某些情况下,非 存活 的值会被从 WeakMap 的键中移除,详见 9.9.3

实现可能会对 WeakMap 的某个键/值对变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript 的实现不得提供任何无需观察者持有该键即可观察 WeakMap 键的手段。

WeakMap 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的键/值对访问时间。本规范中所用的数据结构仅用于描述 WeakMap 所需的可观察语义,而非实际的实现模型。

WeakMap 和 WeakSet 旨在为对象或符号动态关联状态,且如果没有 WeakMap 或 WeakSet 实例,该对象或符号变得不可访问并被垃圾回收机制回收时,不会“泄漏”内存资源。可以通过将 WeakMap 或 WeakSet 实例反向映射到每个对象/符号实现这一特性。或者,每个 WeakMap 或 WeakSet 实例可以内部存储其键和值数据,但这种方法需要 WeakMap/WeakSet 实现与垃圾回收器协作。下列参考文献介绍了对 WeakMap 和 WeakSet 实现可能有用的机制:

Barry Hayes. 1997. Ephemerons: a new finalization mechanism. 载于 Proceedings of the 12th ACM SIGPLAN conference on Object-oriented programming, systems, languages, and applications (OOPSLA '97), A. Michael Berman (编辑). ACM, New York, NY, USA, 176-183, http://doi.acm.org/10.1145/263698.263733.

Alexandra Barros, Roberto Ierusalimschy, Eliminating Cycles in Weak Tables. Journal of Universal Computer Science - J.UCS, vol. 14, no. 21, pp. 3481-3497, 2008, http://www.jucs.org/jucs_14_21/eliminating_cycles_in_weak

24.3.1 WeakMap 构造函数

WeakMap 构造函数

  • %WeakMap%
  • 全局对象"WeakMap" 属性的初始值。
  • 作为 构造函数 调用时会创建并初始化一个新的 WeakMap。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 WeakMap 行为的子类 构造函数 必须包含对 WeakMap 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 WeakMap.prototype 内建方法。

24.3.1.1 WeakMap ( [ iterable ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. map 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakMap.prototype%", « [[WeakMapData]] »)。
  3. 设置 map.[[WeakMapData]] 为一个新的空 List
  4. 如果 iterableundefinednull,返回 map
  5. adder 为 ? Get(map, "set")。
  6. 如果 IsCallable(adder) 为 false,抛出 TypeError 异常。
  7. 返回 ? AddEntriesFromIterable(map, iterable, adder)。

如果参数 iterable 存在,期望它是一个实现了 %Symbol.iterator% 方法的对象,该方法返回一个 迭代器对象,会产生一个二元素 类数组对象,其第一个元素作为 WeakMap 的键,第二个元素为要与该键关联的值。

24.3.2 WeakMap 构造函数的属性

WeakMap 构造函数

24.3.2.1 WeakMap.prototype

WeakMap.prototype 的初始值为 WeakMap 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.3.3 WeakMap 原型对象的属性

WeakMap 原型对象

  • %WeakMap.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[WeakMapData]] 内部槽。

24.3.3.1 WeakMap.prototype.constructor

WeakMap.prototype.constructor 的初始值为 %WeakMap%

24.3.3.2 WeakMap.prototype.delete ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Key]] 设为 empty
      2. p.[[Value]] 设为 empty
      3. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.3.3.3 WeakMap.prototype.get ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 undefined
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 p.[[Value]]
  5. 返回 undefined

24.3.3.4 WeakMap.prototype.has ( key )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,返回 false
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,返回 true
  5. 返回 false

24.3.3.5 WeakMap.prototype.set ( key, value )

该方法被调用时执行以下步骤:

  1. Mthis 值。
  2. 执行 ? RequireInternalSlot(M, [[WeakMapData]])。
  3. 如果 CanBeHeldWeakly(key) 为 false,抛出 TypeError 异常。
  4. 对于 M.[[WeakMapData]] 中的每个 Record { [[Key]], [[Value]] } p,执行
    1. 如果 p.[[Key]] 不为 emptySameValue(p.[[Key]], key) 为 true,则
      1. p.[[Value]] 设为 value
      2. 返回 M
  5. pRecord { [[Key]]: key, [[Value]]: value }。
  6. p 添加到 M.[[WeakMapData]]
  7. 返回 M

24.3.3.6 WeakMap.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "WeakMap"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.3.4 WeakMap 实例的属性

WeakMap 实例是 普通对象,它们继承自 WeakMap 原型的属性。WeakMap 实例还拥有 [[WeakMapData]] 内部槽。

24.4 WeakSet 对象

WeakSet 是对象和/或符号的集合。在 WeakSet 的集合中,每个不同的对象或符号只能出现一次。WeakSet 可以用来查询是否包含某个特定值,但没有机制用于枚举它所持有的所有值。在某些情况下,非 存活 的值会被从 WeakSet 元素中移除,详见 9.9.3

实现可能会对 WeakSet 所包含的某个值变得不可访问与被移除之间施加任意的延迟。如果这个延迟对 ECMAScript 程序是可观察的,则会带来不确定性,影响程序执行。因此,ECMAScript 的实现不得提供任何无需观察者持有该值即可确定 WeakSet 是否包含该值的手段。

WeakSet 必须通过哈希表或其他机制实现,这些机制在平均情况下能提供次线性的元素访问时间。本规范中所用的数据结构仅用于描述 WeakSet 所需的可观察语义,而非实际的实现模型。

参见 24.3 中的注。

24.4.1 WeakSet 构造函数

WeakSet 构造函数

  • %WeakSet%
  • 全局对象"WeakSet" 属性的初始值。
  • 作为 构造函数 调用时会创建并初始化一个新的 WeakSet。
  • 不应作为普通函数调用,否则会抛出异常。
  • 可以用作类定义的 extends 子句的值。想要继承指定 WeakSet 行为的子类 构造函数 必须包含对 WeakSet 构造函数super 调用,以用必要的内部状态创建和初始化子类实例,以支持 WeakSet.prototype 内建方法。

24.4.1.1 WeakSet ( [ iterable ] )

该函数被调用时执行以下步骤:

  1. 如果 NewTarget 为 undefined,抛出 TypeError 异常。
  2. set 为 ? OrdinaryCreateFromConstructor(NewTarget, "%WeakSet.prototype%", « [[WeakSetData]] »)。
  3. 设置 set.[[WeakSetData]] 为一个新的空 List
  4. 如果 iterableundefinednull,返回 set
  5. adder 为 ? Get(set, "add")。
  6. 如果 IsCallable(adder) 为 false,抛出 TypeError 异常。
  7. iteratorRecord 为 ? GetIterator(iterable, sync)。
  8. 重复,
    1. next 为 ? IteratorStepValue(iteratorRecord)。
    2. 如果 nextdone,返回 set
    3. statusCompletion(Call(adder, set, « next »))。
    4. IfAbruptCloseIterator(status, iteratorRecord)。

24.4.2 WeakSet 构造函数的属性

WeakSet 构造函数

24.4.2.1 WeakSet.prototype

WeakSet.prototype 的初始值为 WeakSet 原型对象

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }。

24.4.3 WeakSet 原型对象的属性

WeakSet 原型对象

  • %WeakSet.prototype%
  • 拥有一个 [[Prototype]] 内部槽,其值为 %Object.prototype%
  • 是一个 普通对象
  • 没有 [[WeakSetData]] 内部槽。

24.4.3.1 WeakSet.prototype.add ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,抛出 TypeError 异常。
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. 返回 S
  5. value 添加到 S.[[WeakSetData]]
  6. 返回 S

24.4.3.2 WeakSet.prototype.constructor

WeakSet.prototype.constructor 的初始值为 %WeakSet%

24.4.3.3 WeakSet.prototype.delete ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,返回 false
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,则
      1. S.[[WeakSetData]] 中值为 e 的元素替换为值为 empty 的元素。
      2. 返回 true
  5. 返回 false

empty 作为规范设备用来表示一个条目已被删除。实际实现可能会采取其他操作,比如在内部数据结构中物理删除该条目。

24.4.3.4 WeakSet.prototype.has ( value )

该方法被调用时执行以下步骤:

  1. Sthis 值。
  2. 执行 ? RequireInternalSlot(S, [[WeakSetData]])。
  3. 如果 CanBeHeldWeakly(value) 为 false,返回 false
  4. 对于 S.[[WeakSetData]] 的每个元素 e,执行
    1. 如果 e 不为 emptySameValue(e, value) 为 true,返回 true
  5. 返回 false

24.4.3.5 WeakSet.prototype [ %Symbol.toStringTag% ]

%Symbol.toStringTag% 属性的初始值为字符串值 "WeakSet"

该属性具有属性 { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }。

24.4.4 WeakSet 实例的属性

WeakSet 实例是 普通对象,它们继承自 WeakSet 原型的属性。WeakSet 实例还拥有 [[WeakSetData]] 内部槽。

24.5 键控集合的抽象操作

24.5.1 CanonicalizeKeyedCollectionKey ( key )

抽象操作 CanonicalizeKeyedCollectionKey 接收参数 key(一个 ECMAScript 语言值),并返回一个 ECMAScript 语言值。调用时执行以下步骤:

  1. 如果 key-0𝔽,返回 +0𝔽
  2. 返回 key

25 Structured Data

25.1 ArrayBuffer Objects

25.1.1 Notation

The descriptions below in this section, 25.4, and 29 use the read-modify-write modification function internal data structure.

A read-modify-write modification function is a mathematical function that is represented as an abstract closure that takes two Lists of byte values as arguments and returns a List of byte values. These abstract closures satisfy all of the following properties:

  • They perform all their algorithm steps atomically.
  • Their individual algorithm steps are not observable.
Note

To aid verifying that a read-modify-write modification function's algorithm steps constitute a pure, mathematical function, the following editorial conventions are recommended:

25.1.2 Fixed-length and Resizable ArrayBuffer Objects

A fixed-length ArrayBuffer is an ArrayBuffer whose byte length cannot change after creation.

A resizable ArrayBuffer is an ArrayBuffer whose byte length may change after creation via calls to ArrayBuffer.prototype.resize ( newLength ).

The kind of ArrayBuffer object that is created depends on the arguments passed to ArrayBuffer ( length [ , options ] ).

25.1.3 Abstract Operations For ArrayBuffer Objects

25.1.3.1 AllocateArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateArrayBuffer takes arguments constructor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns either a normal completion containing an ArrayBuffer or a throw completion. It is used to create an ArrayBuffer. It performs the following steps when called:

  1. Let slots be « [[ArrayBufferData]], [[ArrayBufferByteLength]], [[ArrayBufferDetachKey]] ».
  2. If maxByteLength is present and maxByteLength is not empty, let allocatingResizableBuffer be true; otherwise let allocatingResizableBuffer be false.
  3. If allocatingResizableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferMaxByteLength]] to slots.
  4. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%ArrayBuffer.prototype%", slots).
  5. Let block be ? CreateByteDataBlock(byteLength).
  6. Set obj.[[ArrayBufferData]] to block.
  7. Set obj.[[ArrayBufferByteLength]] to byteLength.
  8. If allocatingResizableBuffer is true, then
    1. If it is not possible to create a Data Block block consisting of maxByteLength bytes, throw a RangeError exception.
    2. NOTE: Resizable ArrayBuffers are designed to be implementable with in-place growth. Implementations may throw if, for example, virtual memory cannot be reserved up front.
    3. Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength.
  9. Return obj.

25.1.3.2 ArrayBufferByteLength ( arrayBuffer, order )

The abstract operation ArrayBufferByteLength takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer) and order (seq-cst or unordered) and returns a non-negative integer. It performs the following steps when called:

  1. If IsSharedArrayBuffer(arrayBuffer) is true and arrayBuffer has an [[ArrayBufferByteLengthData]] internal slot, then
    1. Let bufferByteLengthBlock be arrayBuffer.[[ArrayBufferByteLengthData]].
    2. Let rawLength be GetRawBytesFromSharedBlock(bufferByteLengthBlock, 0, biguint64, true, order).
    3. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
    4. Return (RawBytesToNumeric(biguint64, rawLength, isLittleEndian)).
  2. Assert: IsDetachedBuffer(arrayBuffer) is false.
  3. Return arrayBuffer.[[ArrayBufferByteLength]].

25.1.3.3 ArrayBufferCopyAndDetach ( arrayBuffer, newLength, preserveResizability )

The abstract operation ArrayBufferCopyAndDetach takes arguments arrayBuffer (an ECMAScript language value), newLength (an ECMAScript language value), and preserveResizability (preserve-resizability or fixed-length) and returns either a normal completion containing an ArrayBuffer or a throw completion. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(arrayBuffer, [[ArrayBufferData]]).
  2. If IsSharedArrayBuffer(arrayBuffer) is true, throw a TypeError exception.
  3. If newLength is undefined, then
    1. Let newByteLength be arrayBuffer.[[ArrayBufferByteLength]].
  4. Else,
    1. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(arrayBuffer) is true, throw a TypeError exception.
  6. If preserveResizability is preserve-resizability and IsFixedLengthArrayBuffer(arrayBuffer) is false, then
    1. Let newMaxByteLength be arrayBuffer.[[ArrayBufferMaxByteLength]].
  7. Else,
    1. Let newMaxByteLength be empty.
  8. If arrayBuffer.[[ArrayBufferDetachKey]] is not undefined, throw a TypeError exception.
  9. Let newBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, newByteLength, newMaxByteLength).
  10. Let copyLength be min(newByteLength, arrayBuffer.[[ArrayBufferByteLength]]).
  11. Let fromBlock be arrayBuffer.[[ArrayBufferData]].
  12. Let toBlock be newBuffer.[[ArrayBufferData]].
  13. Perform CopyDataBlockBytes(toBlock, 0, fromBlock, 0, copyLength).
  14. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as a zero-copy move or a realloc.
  15. Perform ! DetachArrayBuffer(arrayBuffer).
  16. Return newBuffer.

25.1.3.4 IsDetachedBuffer ( arrayBuffer )

The abstract operation IsDetachedBuffer takes argument arrayBuffer (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It performs the following steps when called:

  1. If arrayBuffer.[[ArrayBufferData]] is null, return true.
  2. Return false.

25.1.3.5 DetachArrayBuffer ( arrayBuffer [ , key ] )

The abstract operation DetachArrayBuffer takes argument arrayBuffer (an ArrayBuffer) and optional argument key (anything) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. Assert: IsSharedArrayBuffer(arrayBuffer) is false.
  2. If key is not present, set key to undefined.
  3. If arrayBuffer.[[ArrayBufferDetachKey]] is not key, throw a TypeError exception.
  4. Set arrayBuffer.[[ArrayBufferData]] to null.
  5. Set arrayBuffer.[[ArrayBufferByteLength]] to 0.
  6. Return unused.
Note

Detaching an ArrayBuffer instance disassociates the Data Block used as its backing store from the instance and sets the byte length of the buffer to 0.

25.1.3.6 CloneArrayBuffer ( srcBuffer, srcByteOffset, srcLength )

The abstract operation CloneArrayBuffer takes arguments srcBuffer (an ArrayBuffer or a SharedArrayBuffer), srcByteOffset (a non-negative integer), and srcLength (a non-negative integer) and returns either a normal completion containing an ArrayBuffer or a throw completion. It creates a new ArrayBuffer whose data is a copy of srcBuffer's data over the range starting at srcByteOffset and continuing for srcLength bytes. It performs the following steps when called:

  1. Assert: IsDetachedBuffer(srcBuffer) is false.
  2. Let targetBuffer be ? AllocateArrayBuffer(%ArrayBuffer%, srcLength).
  3. Let srcBlock be srcBuffer.[[ArrayBufferData]].
  4. Let targetBlock be targetBuffer.[[ArrayBufferData]].
  5. Perform CopyDataBlockBytes(targetBlock, 0, srcBlock, srcByteOffset, srcLength).
  6. Return targetBuffer.

25.1.3.7 GetArrayBufferMaxByteLengthOption ( options )

The abstract operation GetArrayBufferMaxByteLengthOption takes argument options (an ECMAScript language value) and returns either a normal completion containing either a non-negative integer or empty, or a throw completion. It performs the following steps when called:

  1. If options is not an Object, return empty.
  2. Let maxByteLength be ? Get(options, "maxByteLength").
  3. If maxByteLength is undefined, return empty.
  4. Return ? ToIndex(maxByteLength).

25.1.3.8 HostResizeArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostResizeArrayBuffer takes arguments buffer (an ArrayBuffer) and newByteLength (a non-negative integer) and returns either a normal completion containing either handled or unhandled, or a throw completion. It gives the host an opportunity to perform implementation-defined resizing of buffer. If the host chooses not to handle resizing of buffer, it may return unhandled for the default behaviour.

The implementation of HostResizeArrayBuffer must conform to the following requirements:

  • The abstract operation does not detach buffer.
  • If the abstract operation completes normally with handled, buffer.[[ArrayBufferByteLength]] is newByteLength.

The default implementation of HostResizeArrayBuffer is to return NormalCompletion(unhandled).

25.1.3.9 IsFixedLengthArrayBuffer ( arrayBuffer )

The abstract operation IsFixedLengthArrayBuffer takes argument arrayBuffer (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It performs the following steps when called:

  1. If arrayBuffer has an [[ArrayBufferMaxByteLength]] internal slot, return false.
  2. Return true.

25.1.3.10 IsUnsignedElementType ( type )

The abstract operation IsUnsignedElementType takes argument type (a TypedArray element type) and returns a Boolean. It verifies if the argument type is an unsigned TypedArray element type. It performs the following steps when called:

  1. If type is one of uint8, uint8clamped, uint16, uint32, or biguint64, return true.
  2. Return false.

25.1.3.11 IsUnclampedIntegerElementType ( type )

The abstract operation IsUnclampedIntegerElementType takes argument type (a TypedArray element type) and returns a Boolean. It verifies if the argument type is an Integer TypedArray element type not including uint8clamped. It performs the following steps when called:

  1. If type is one of int8, uint8, int16, uint16, int32, or uint32, return true.
  2. Return false.

25.1.3.12 IsBigIntElementType ( type )

The abstract operation IsBigIntElementType takes argument type (a TypedArray element type) and returns a Boolean. It verifies if the argument type is a BigInt TypedArray element type. It performs the following steps when called:

  1. If type is either biguint64 or bigint64, return true.
  2. Return false.

25.1.3.13 IsNoTearConfiguration ( type, order )

The abstract operation IsNoTearConfiguration takes arguments type (a TypedArray element type) and order (seq-cst, unordered, or init) and returns a Boolean. It performs the following steps when called:

  1. If IsUnclampedIntegerElementType(type) is true, return true.
  2. If IsBigIntElementType(type) is true and order is neither init nor unordered, return true.
  3. Return false.

25.1.3.14 RawBytesToNumeric ( type, rawBytes, isLittleEndian )

The abstract operation RawBytesToNumeric takes arguments type (a TypedArray element type), rawBytes (a List of byte values), and isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  2. If isLittleEndian is false, reverse the order of the elements of rawBytes.
  3. If type is float16, then
    1. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary16 value.
    2. If value is a NaN, return NaN.
    3. Return the Number value that corresponds to value.
  4. If type is float32, then
    1. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary32 value.
    2. If value is a NaN, return NaN.
    3. Return the Number value that corresponds to value.
  5. If type is float64, then
    1. Let value be the byte elements of rawBytes concatenated and interpreted as a little-endian bit string encoding of an IEEE 754-2019 binary64 value.
    2. If value is a NaN, return NaN.
    3. Return the Number value that corresponds to value.
  6. If IsUnsignedElementType(type) is true, then
    1. Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of an unsigned little-endian binary number.
  7. Else,
    1. Let intValue be the byte elements of rawBytes concatenated and interpreted as a bit string encoding of a binary little-endian two's complement number of bit length elementSize × 8.
  8. If IsBigIntElementType(type) is true, return the BigInt value that corresponds to intValue.
  9. Otherwise, return the Number value that corresponds to intValue.

25.1.3.15 GetRawBytesFromSharedBlock ( block, byteIndex, type, isTypedArray, order )

The abstract operation GetRawBytesFromSharedBlock takes arguments block (a Shared Data Block), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (seq-cst or unordered) and returns a List of byte values. It performs the following steps when called:

  1. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  2. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
  3. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
  4. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
  5. Let rawValue be a List of length elementSize whose elements are nondeterministically chosen byte values.
  6. NOTE: In implementations, rawValue is the result of a non-atomic or atomic read instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
  7. Let readEvent be ReadSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize }.
  8. Append readEvent to eventsRecord.[[EventList]].
  9. Append Chosen Value Record { [[Event]]: readEvent, [[ChosenValue]]: rawValue } to execution.[[ChosenValues]].
  10. Return rawValue.

25.1.3.16 GetValueFromBuffer ( arrayBuffer, byteIndex, type, isTypedArray, order [ , isLittleEndian ] )

The abstract operation GetValueFromBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), isTypedArray (a Boolean), and order (seq-cst or unordered) and optional argument isLittleEndian (a Boolean) and returns a Number or a BigInt. It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Let block be arrayBuffer.[[ArrayBufferData]].
  4. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  5. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Assert: block is a Shared Data Block.
    2. Let rawValue be GetRawBytesFromSharedBlock(block, byteIndex, type, isTypedArray, order).
  6. Else,
    1. Let rawValue be a List whose elements are bytes from block at indices in the interval from byteIndex (inclusive) to byteIndex + elementSize (exclusive).
  7. Assert: The number of elements in rawValue is elementSize.
  8. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  9. Return RawBytesToNumeric(type, rawValue, isLittleEndian).

25.1.3.17 NumericToRawBytes ( type, value, isLittleEndian )

The abstract operation NumericToRawBytes takes arguments type (a TypedArray element type), value (a Number or a BigInt), and isLittleEndian (a Boolean) and returns a List of byte values. It performs the following steps when called:

  1. If type is float16, then
    1. Let rawBytes be a List whose elements are the 2 bytes that are the result of converting value to IEEE 754-2019 binary16 format using roundTiesToEven mode. The bytes are arranged in little endian order. If value is NaN, rawBytes may be set to any implementation chosen IEEE 754-2019 binary16 format NaN encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
  2. Else if type is float32, then
    1. Let rawBytes be a List whose elements are the 4 bytes that are the result of converting value to IEEE 754-2019 binary32 format using roundTiesToEven mode. The bytes are arranged in little endian order. If value is NaN, rawBytes may be set to any implementation chosen IEEE 754-2019 binary32 format NaN encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
  3. Else if type is float64, then
    1. Let rawBytes be a List whose elements are the 8 bytes that are the IEEE 754-2019 binary64 format encoding of value. The bytes are arranged in little endian order. If value is NaN, rawBytes may be set to any implementation chosen IEEE 754-2019 binary64 format NaN encoding. An implementation must always choose the same encoding for each implementation distinguishable NaN value.
  4. Else,
    1. Let n be the Element Size value specified in Table 75 for Element Type type.
    2. Let conversionOperation be the abstract operation named in the Conversion Operation column in Table 75 for Element Type type.
    3. Let intValue be (conversionOperation(value)).
    4. If intValue ≥ 0, then
      1. Let rawBytes be a List whose elements are the n-byte binary encoding of intValue. The bytes are ordered in little endian order.
    5. Else,
      1. Let rawBytes be a List whose elements are the n-byte binary two's complement encoding of intValue. The bytes are ordered in little endian order.
  5. If isLittleEndian is false, reverse the order of the elements of rawBytes.
  6. Return rawBytes.

25.1.3.18 SetValueInBuffer ( arrayBuffer, byteIndex, type, value, isTypedArray, order [ , isLittleEndian ] )

The abstract operation SetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), isTypedArray (a Boolean), and order (seq-cst, unordered, or init) and optional argument isLittleEndian (a Boolean) and returns unused. It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  4. Let block be arrayBuffer.[[ArrayBufferData]].
  5. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  6. If isLittleEndian is not present, set isLittleEndian to the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  7. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  8. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. If isTypedArray is true and IsNoTearConfiguration(type, order) is true, let noTear be true; otherwise let noTear be false.
    4. Append WriteSharedMemory { [[Order]]: order, [[NoTear]]: noTear, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes } to eventsRecord.[[EventList]].
  9. Else,
    1. Store the individual bytes of rawBytes into block, starting at block[byteIndex].
  10. Return unused.

25.1.3.19 GetModifySetValueInBuffer ( arrayBuffer, byteIndex, type, value, op )

The abstract operation GetModifySetValueInBuffer takes arguments arrayBuffer (an ArrayBuffer or a SharedArrayBuffer), byteIndex (a non-negative integer), type (a TypedArray element type), value (a Number or a BigInt), and op (a read-modify-write modification function) and returns a Number or a BigInt. It performs the following steps when called:

  1. Assert: IsDetachedBuffer(arrayBuffer) is false.
  2. Assert: There are sufficient bytes in arrayBuffer starting at byteIndex to represent a value of type.
  3. Assert: value is a BigInt if IsBigIntElementType(type) is true; otherwise, value is a Number.
  4. Let block be arrayBuffer.[[ArrayBufferData]].
  5. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  6. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  7. Let rawBytes be NumericToRawBytes(type, value, isLittleEndian).
  8. If IsSharedArrayBuffer(arrayBuffer) is true, then
    1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
    4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
    5. Let rmwEvent be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndex, [[ElementSize]]: elementSize, [[Payload]]: rawBytes, [[ModifyOp]]: op }.
    6. Append rmwEvent to eventsRecord.[[EventList]].
    7. Append Chosen Value Record { [[Event]]: rmwEvent, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  9. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndex].
    2. Let rawBytesModified be op(rawBytesRead, rawBytes).
    3. Store the individual bytes of rawBytesModified into block, starting at block[byteIndex].
  10. Return RawBytesToNumeric(type, rawBytesRead, isLittleEndian).

25.1.4 The ArrayBuffer Constructor

The ArrayBuffer constructor:

  • is %ArrayBuffer%.
  • is the initial value of the "ArrayBuffer" property of the global object.
  • creates and initializes a new ArrayBuffer when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified ArrayBuffer behaviour must include a super call to the ArrayBuffer constructor to create and initialize subclass instances with the internal state necessary to support the ArrayBuffer.prototype built-in methods.

25.1.4.1 ArrayBuffer ( length [ , options ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let byteLength be ? ToIndex(length).
  3. Let requestedMaxByteLength be ? GetArrayBufferMaxByteLengthOption(options).
  4. Return ? AllocateArrayBuffer(NewTarget, byteLength, requestedMaxByteLength).

25.1.5 Properties of the ArrayBuffer Constructor

The ArrayBuffer constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

25.1.5.1 ArrayBuffer.isView ( arg )

This function performs the following steps when called:

  1. If arg is not an Object, return false.
  2. If arg has a [[ViewedArrayBuffer]] internal slot, return true.
  3. Return false.

25.1.5.2 ArrayBuffer.prototype

The initial value of ArrayBuffer.prototype is the ArrayBuffer prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

25.1.5.3 get ArrayBuffer [ %Symbol.species% ]

ArrayBuffer[%Symbol.species%] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Return the this value.

The value of the "name" property of this function is "get [Symbol.species]".

Note

ArrayBuffer.prototype.slice ( start, end ) normally uses its this value's constructor to create a derived object. However, a subclass constructor may over-ride that default behaviour for the ArrayBuffer.prototype.slice ( start, end ) method by redefining its %Symbol.species% property.

25.1.6 Properties of the ArrayBuffer Prototype Object

The ArrayBuffer prototype object:

  • is %ArrayBuffer.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have an [[ArrayBufferData]] or [[ArrayBufferByteLength]] internal slot.

25.1.6.1 get ArrayBuffer.prototype.byteLength

ArrayBuffer.prototype.byteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, return +0𝔽.
  5. Let length be O.[[ArrayBufferByteLength]].
  6. Return 𝔽(length).

25.1.6.2 ArrayBuffer.prototype.constructor

The initial value of ArrayBuffer.prototype.constructor is %ArrayBuffer%.

25.1.6.3 get ArrayBuffer.prototype.detached

ArrayBuffer.prototype.detached is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Return IsDetachedBuffer(O).

25.1.6.4 get ArrayBuffer.prototype.maxByteLength

ArrayBuffer.prototype.maxByteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, return +0𝔽.
  5. If IsFixedLengthArrayBuffer(O) is true, then
    1. Let length be O.[[ArrayBufferByteLength]].
  6. Else,
    1. Let length be O.[[ArrayBufferMaxByteLength]].
  7. Return 𝔽(length).

25.1.6.5 get ArrayBuffer.prototype.resizable

ArrayBuffer.prototype.resizable is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsFixedLengthArrayBuffer(O) is false, return true; otherwise return false.

25.1.6.6 ArrayBuffer.prototype.resize ( newLength )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  6. If newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  7. Let hostHandled be ? HostResizeArrayBuffer(O, newByteLength).
  8. If hostHandled is handled, return undefined.
  9. Let oldBlock be O.[[ArrayBufferData]].
  10. Let newBlock be ? CreateByteDataBlock(newByteLength).
  11. Let copyLength be min(newByteLength, O.[[ArrayBufferByteLength]]).
  12. Perform CopyDataBlockBytes(newBlock, 0, oldBlock, 0, copyLength).
  13. NOTE: Neither creation of the new Data Block nor copying from the old Data Block are observable. Implementations may implement this method as in-place growth or shrinkage.
  14. Set O.[[ArrayBufferData]] to newBlock.
  15. Set O.[[ArrayBufferByteLength]] to newByteLength.
  16. Return undefined.

25.1.6.7 ArrayBuffer.prototype.slice ( start, end )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is true, throw a TypeError exception.
  4. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  5. Let len be O.[[ArrayBufferByteLength]].
  6. Let relativeStart be ? ToIntegerOrInfinity(start).
  7. If relativeStart = -∞, let first be 0.
  8. Else if relativeStart < 0, let first be max(len + relativeStart, 0).
  9. Else, let first be min(relativeStart, len).
  10. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  11. If relativeEnd = -∞, let final be 0.
  12. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
  13. Else, let final be min(relativeEnd, len).
  14. Let newLen be max(final - first, 0).
  15. Let ctor be ? SpeciesConstructor(O, %ArrayBuffer%).
  16. Let new be ? Construct(ctor, « 𝔽(newLen) »).
  17. Perform ? RequireInternalSlot(new, [[ArrayBufferData]]).
  18. If IsSharedArrayBuffer(new) is true, throw a TypeError exception.
  19. If IsDetachedBuffer(new) is true, throw a TypeError exception.
  20. If SameValue(new, O) is true, throw a TypeError exception.
  21. If new.[[ArrayBufferByteLength]] < newLen, throw a TypeError exception.
  22. NOTE: Side-effects of the above steps may have detached or resized O.
  23. If IsDetachedBuffer(O) is true, throw a TypeError exception.
  24. Let fromBuf be O.[[ArrayBufferData]].
  25. Let toBuf be new.[[ArrayBufferData]].
  26. Let currentLen be O.[[ArrayBufferByteLength]].
  27. If first < currentLen, then
    1. Let count be min(newLen, currentLen - first).
    2. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, count).
  28. Return new.

25.1.6.8 ArrayBuffer.prototype.transfer ( [ newLength ] )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, preserve-resizability).

25.1.6.9 ArrayBuffer.prototype.transferToFixedLength ( [ newLength ] )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Return ? ArrayBufferCopyAndDetach(O, newLength, fixed-length).

25.1.6.10 ArrayBuffer.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "ArrayBuffer".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

25.1.7 Properties of ArrayBuffer Instances

ArrayBuffer instances inherit properties from the ArrayBuffer prototype object. ArrayBuffer instances each have an [[ArrayBufferData]] internal slot, an [[ArrayBufferByteLength]] internal slot, and an [[ArrayBufferDetachKey]] internal slot. ArrayBuffer instances which are resizable each have an [[ArrayBufferMaxByteLength]] internal slot.

ArrayBuffer instances whose [[ArrayBufferData]] is null are considered to be detached and all operators to access or modify data contained in the ArrayBuffer instance will fail.

ArrayBuffer instances whose [[ArrayBufferDetachKey]] is set to a value other than undefined need to have all DetachArrayBuffer calls passing that same "detach key" as an argument, otherwise a TypeError will result. This internal slot is only ever set by certain embedding environments, not by algorithms in this specification.

25.1.8 Resizable ArrayBuffer Guidelines

Note 1

The following are guidelines for ECMAScript programmers working with resizable ArrayBuffer.

We recommend that programs be tested in their deployment environments where possible. The amount of available physical memory differs greatly between hardware devices. Similarly, virtual memory subsystems also differ greatly between hardware devices as well as operating systems. An application that runs without out-of-memory errors on a 64-bit desktop web browser could run out of memory on a 32-bit mobile web browser.

When choosing a value for the "maxByteLength" option for resizable ArrayBuffer, we recommend that the smallest possible size for the application be chosen. We recommend that "maxByteLength" does not exceed 1,073,741,824 (230 bytes or 1GiB).

Please note that successfully constructing a resizable ArrayBuffer for a particular maximum size does not guarantee that future resizes will succeed.

Note 2

The following are guidelines for ECMAScript implementers implementing resizable ArrayBuffer.

Resizable ArrayBuffer can be implemented as copying upon resize, as in-place growth via reserving virtual memory up front, or as a combination of both for different values of the constructor's "maxByteLength" option.

If a host is multi-tenanted (i.e. it runs many ECMAScript applications simultaneously), such as a web browser, and its implementations choose to implement in-place growth by reserving virtual memory, we recommend that both 32-bit and 64-bit implementations throw for values of "maxByteLength" ≥ 1GiB to 1.5GiB. This is to reduce the likelihood a single application can exhaust the virtual memory address space and to reduce interoperability risk.

If a host does not have virtual memory, such as those running on embedded devices without an MMU, or if a host only implements resizing by copying, it may accept any Number value for the "maxByteLength" option. However, we recommend a RangeError be thrown if a memory block of the requested size can never be allocated. For example, if the requested size is greater than the maximum amount of usable memory on the device.

25.2 SharedArrayBuffer Objects

25.2.1 Fixed-length and Growable SharedArrayBuffer Objects

A fixed-length SharedArrayBuffer is a SharedArrayBuffer whose byte length cannot change after creation.

A growable SharedArrayBuffer is a SharedArrayBuffer whose byte length may increase after creation via calls to SharedArrayBuffer.prototype.grow ( newLength ).

The kind of SharedArrayBuffer object that is created depends on the arguments passed to SharedArrayBuffer ( length [ , options ] ).

25.2.2 Abstract Operations for SharedArrayBuffer Objects

25.2.2.1 AllocateSharedArrayBuffer ( constructor, byteLength [ , maxByteLength ] )

The abstract operation AllocateSharedArrayBuffer takes arguments constructor (a constructor) and byteLength (a non-negative integer) and optional argument maxByteLength (a non-negative integer or empty) and returns either a normal completion containing a SharedArrayBuffer or a throw completion. It is used to create a SharedArrayBuffer. It performs the following steps when called:

  1. Let slots be « [[ArrayBufferData]] ».
  2. If maxByteLength is present and maxByteLength is not empty, let allocatingGrowableBuffer be true; otherwise let allocatingGrowableBuffer be false.
  3. If allocatingGrowableBuffer is true, then
    1. If byteLength > maxByteLength, throw a RangeError exception.
    2. Append [[ArrayBufferByteLengthData]] and [[ArrayBufferMaxByteLength]] to slots.
  4. Else,
    1. Append [[ArrayBufferByteLength]] to slots.
  5. Let obj be ? OrdinaryCreateFromConstructor(constructor, "%SharedArrayBuffer.prototype%", slots).
  6. If allocatingGrowableBuffer is true, let allocLength be maxByteLength; otherwise let allocLength be byteLength.
  7. Let block be ? CreateSharedByteDataBlock(allocLength).
  8. Set obj.[[ArrayBufferData]] to block.
  9. If allocatingGrowableBuffer is true, then
    1. Assert: byteLengthmaxByteLength.
    2. Let byteLengthBlock be ? CreateSharedByteDataBlock(8).
    3. Perform SetValueInBuffer(byteLengthBlock, 0, biguint64, (byteLength), true, seq-cst).
    4. Set obj.[[ArrayBufferByteLengthData]] to byteLengthBlock.
    5. Set obj.[[ArrayBufferMaxByteLength]] to maxByteLength.
  10. Else,
    1. Set obj.[[ArrayBufferByteLength]] to byteLength.
  11. Return obj.

25.2.2.2 IsSharedArrayBuffer ( obj )

The abstract operation IsSharedArrayBuffer takes argument obj (an ArrayBuffer or a SharedArrayBuffer) and returns a Boolean. It tests whether an object is an ArrayBuffer, a SharedArrayBuffer, or a subtype of either. It performs the following steps when called:

  1. Let bufferData be obj.[[ArrayBufferData]].
  2. If bufferData is null, return false.
  3. If bufferData is a Data Block, return false.
  4. Assert: bufferData is a Shared Data Block.
  5. Return true.

25.2.2.3 HostGrowSharedArrayBuffer ( buffer, newByteLength )

The host-defined abstract operation HostGrowSharedArrayBuffer takes arguments buffer (a SharedArrayBuffer) and newByteLength (a non-negative integer) and returns either a normal completion containing either handled or unhandled, or a throw completion. It gives the host an opportunity to perform implementation-defined growing of buffer. If the host chooses not to handle growing of buffer, it may return unhandled for the default behaviour.

The implementation of HostGrowSharedArrayBuffer must conform to the following requirements:

  • If the abstract operation does not complete normally with unhandled, and newByteLength < the current byte length of the buffer or newByteLength > buffer.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
  • Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record. If the abstract operation completes normally with handled, a WriteSharedMemory or ReadModifyWriteSharedMemory event whose [[Order]] is seq-cst, [[Payload]] is NumericToRawBytes(biguint64, newByteLength, isLittleEndian), [[Block]] is buffer.[[ArrayBufferByteLengthData]], [[ByteIndex]] is 0, and [[ElementSize]] is 8 is added to the surrounding agent's candidate execution such that racing calls to SharedArrayBuffer.prototype.grow are not "lost", i.e. silently do nothing.
Note

The second requirement above is intentionally vague about how or when the current byte length of buffer is read. Because the byte length must be updated via an atomic read-modify-write operation on the underlying hardware, architectures that use load-link/store-conditional or load-exclusive/store-exclusive instruction pairs may wish to keep the paired instructions close in the instruction stream. As such, SharedArrayBuffer.prototype.grow itself does not perform bounds checking on newByteLength before calling HostGrowSharedArrayBuffer, nor is there a requirement on when the current byte length is read.

This is in contrast with HostResizeArrayBuffer, which is guaranteed that the value of newByteLength is ≥ 0 and ≤ buffer.[[ArrayBufferMaxByteLength]].

The default implementation of HostGrowSharedArrayBuffer is to return NormalCompletion(unhandled).

25.2.3 The SharedArrayBuffer Constructor

The SharedArrayBuffer constructor:

  • is %SharedArrayBuffer%.
  • is the initial value of the "SharedArrayBuffer" property of the global object, if that property is present (see below).
  • creates and initializes a new SharedArrayBuffer when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified SharedArrayBuffer behaviour must include a super call to the SharedArrayBuffer constructor to create and initialize subclass instances with the internal state necessary to support the SharedArrayBuffer.prototype built-in methods.

Whenever a host does not provide concurrent access to SharedArrayBuffers it may omit the "SharedArrayBuffer" property of the global object.

Note

Unlike an ArrayBuffer, a SharedArrayBuffer cannot become detached, and its internal [[ArrayBufferData]] slot is never null.

25.2.3.1 SharedArrayBuffer ( length [ , options ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Let byteLength be ? ToIndex(length).
  3. Let requestedMaxByteLength be ? GetArrayBufferMaxByteLengthOption(options).
  4. Return ? AllocateSharedArrayBuffer(NewTarget, byteLength, requestedMaxByteLength).

25.2.4 Properties of the SharedArrayBuffer Constructor

The SharedArrayBuffer constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

25.2.4.1 SharedArrayBuffer.prototype

The initial value of SharedArrayBuffer.prototype is the SharedArrayBuffer prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

25.2.4.2 get SharedArrayBuffer [ %Symbol.species% ]

SharedArrayBuffer[%Symbol.species%] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Return the this value.

The value of the "name" property of this function is "get [Symbol.species]".

25.2.5 Properties of the SharedArrayBuffer Prototype Object

The SharedArrayBuffer prototype object:

  • is %SharedArrayBuffer.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have an [[ArrayBufferData]] or [[ArrayBufferByteLength]] internal slot.

25.2.5.1 get SharedArrayBuffer.prototype.byteLength

SharedArrayBuffer.prototype.byteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
  4. Let length be ArrayBufferByteLength(O, seq-cst).
  5. Return 𝔽(length).

25.2.5.2 SharedArrayBuffer.prototype.constructor

The initial value of SharedArrayBuffer.prototype.constructor is %SharedArrayBuffer%.

25.2.5.3 SharedArrayBuffer.prototype.grow ( newLength )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferMaxByteLength]]).
  3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
  4. Let newByteLength be ? ToIndex(newLength).
  5. Let hostHandled be ? HostGrowSharedArrayBuffer(O, newByteLength).
  6. If hostHandled is handled, return undefined.
  7. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  8. Let byteLengthBlock be O.[[ArrayBufferByteLengthData]].
  9. Let currentByteLengthRawBytes be GetRawBytesFromSharedBlock(byteLengthBlock, 0, biguint64, true, seq-cst).
  10. Let newByteLengthRawBytes be NumericToRawBytes(biguint64, (newByteLength), isLittleEndian).
  11. Repeat,
    1. NOTE: This is a compare-and-exchange loop to ensure that parallel, racing grows of the same buffer are totally ordered, are not lost, and do not silently do nothing. The loop exits if it was able to attempt to grow uncontended.
    2. Let currentByteLength be (RawBytesToNumeric(biguint64, currentByteLengthRawBytes, isLittleEndian)).
    3. If newByteLength = currentByteLength, return undefined.
    4. If newByteLength < currentByteLength or newByteLength > O.[[ArrayBufferMaxByteLength]], throw a RangeError exception.
    5. Let byteLengthDelta be newByteLength - currentByteLength.
    6. If it is impossible to create a new Shared Data Block value consisting of byteLengthDelta bytes, throw a RangeError exception.
    7. NOTE: No new Shared Data Block is constructed and used here. The observable behaviour of growable SharedArrayBuffers is specified by allocating a max-sized Shared Data Block at construction time, and this step captures the requirement that implementations that run out of memory must throw a RangeError.
    8. Let readByteLengthRawBytes be AtomicCompareExchangeInSharedBlock(byteLengthBlock, 0, 8, currentByteLengthRawBytes, newByteLengthRawBytes).
    9. If ByteListEqual(readByteLengthRawBytes, currentByteLengthRawBytes) is true, return undefined.
    10. Set currentByteLengthRawBytes to readByteLengthRawBytes.
Note

Spurious failures of the compare-exchange to update the length are prohibited. If the bounds checking for the new length passes and the implementation is not out of memory, a ReadModifyWriteSharedMemory event (i.e. a successful compare-exchange) is always added into the candidate execution.

Parallel calls to SharedArrayBuffer.prototype.grow are totally ordered. For example, consider two racing calls: sab.grow(10) and sab.grow(20). One of the two calls is guaranteed to win the race. The call to sab.grow(10) will never shrink sab even if sab.grow(20) happened first; in that case it will instead throw a RangeError.

25.2.5.4 get SharedArrayBuffer.prototype.growable

SharedArrayBuffer.prototype.growable is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
  4. If IsFixedLengthArrayBuffer(O) is false, return true; otherwise return false.

25.2.5.5 get SharedArrayBuffer.prototype.maxByteLength

SharedArrayBuffer.prototype.maxByteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
  4. If IsFixedLengthArrayBuffer(O) is true, then
    1. Let length be O.[[ArrayBufferByteLength]].
  5. Else,
    1. Let length be O.[[ArrayBufferMaxByteLength]].
  6. Return 𝔽(length).

25.2.5.6 SharedArrayBuffer.prototype.slice ( start, end )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[ArrayBufferData]]).
  3. If IsSharedArrayBuffer(O) is false, throw a TypeError exception.
  4. Let len be ArrayBufferByteLength(O, seq-cst).
  5. Let relativeStart be ? ToIntegerOrInfinity(start).
  6. If relativeStart = -∞, let first be 0.
  7. Else if relativeStart < 0, let first be max(len + relativeStart, 0).
  8. Else, let first be min(relativeStart, len).
  9. If end is undefined, let relativeEnd be len; else let relativeEnd be ? ToIntegerOrInfinity(end).
  10. If relativeEnd = -∞, let final be 0.
  11. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0).
  12. Else, let final be min(relativeEnd, len).
  13. Let newLen be max(final - first, 0).
  14. Let ctor be ? SpeciesConstructor(O, %SharedArrayBuffer%).
  15. Let new be ? Construct(ctor, « 𝔽(newLen) »).
  16. Perform ? RequireInternalSlot(new, [[ArrayBufferData]]).
  17. If IsSharedArrayBuffer(new) is false, throw a TypeError exception.
  18. If new.[[ArrayBufferData]] is O.[[ArrayBufferData]], throw a TypeError exception.
  19. If ArrayBufferByteLength(new, seq-cst) < newLen, throw a TypeError exception.
  20. Let fromBuf be O.[[ArrayBufferData]].
  21. Let toBuf be new.[[ArrayBufferData]].
  22. Perform CopyDataBlockBytes(toBuf, 0, fromBuf, first, newLen).
  23. Return new.

25.2.5.7 SharedArrayBuffer.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "SharedArrayBuffer".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

25.2.6 Properties of SharedArrayBuffer Instances

SharedArrayBuffer instances inherit properties from the SharedArrayBuffer prototype object. SharedArrayBuffer instances each have an [[ArrayBufferData]] internal slot. SharedArrayBuffer instances which are not growable each have an [[ArrayBufferByteLength]] internal slot. SharedArrayBuffer instances which are growable each have an [[ArrayBufferByteLengthData]] internal slot and an [[ArrayBufferMaxByteLength]] internal slot.

Note

SharedArrayBuffer instances, unlike ArrayBuffer instances, are never detached.

25.2.7 Growable SharedArrayBuffer Guidelines

Note 1

The following are guidelines for ECMAScript programmers working with growable SharedArrayBuffer.

We recommend that programs be tested in their deployment environments where possible. The amount of available physical memory differ greatly between hardware devices. Similarly, virtual memory subsystems also differ greatly between hardware devices as well as operating systems. An application that runs without out-of-memory errors on a 64-bit desktop web browser could run out of memory on a 32-bit mobile web browser.

When choosing a value for the "maxByteLength" option for growable SharedArrayBuffer, we recommend that the smallest possible size for the application be chosen. We recommend that "maxByteLength" does not exceed 1073741824, or 1GiB.

Please note that successfully constructing a growable SharedArrayBuffer for a particular maximum size does not guarantee that future grows will succeed.

Not all loads of a growable SharedArrayBuffer's length are synchronizing seq-cst loads. Loads of the length that are for bounds-checking of an integer-indexed property access, e.g. u8[idx], are not synchronizing. In general, in the absence of explicit synchronization, one property access being in-bound does not imply a subsequent property access in the same agent is also in-bound. In contrast, explicit loads of the length via the length and byteLength getters on SharedArrayBuffer, %TypedArray%.prototype, and DataView.prototype are synchronizing. Loads of the length that are performed by built-in methods to check if a TypedArray is entirely out-of-bounds are also synchronizing.

Note 2

The following are guidelines for ECMAScript implementers implementing growable SharedArrayBuffer.

We recommend growable SharedArrayBuffer be implemented as in-place growth via reserving virtual memory up front.

Because grow operations can happen in parallel with memory accesses on a growable SharedArrayBuffer, the constraints of the memory model require that even unordered accesses do not "tear" (bits of their values will not be mixed). In practice, this means the underlying data block of a growable SharedArrayBuffer cannot be grown by being copied without stopping the world. We do not recommend stopping the world as an implementation strategy because it introduces a serialization point and is slow.

Grown memory must appear zeroed from the moment of its creation, including to any racy accesses in parallel. This can be accomplished via zero-filled-on-demand virtual memory pages, or careful synchronization if manually zeroing memory.

Integer-indexed property access on TypedArray views of growable SharedArrayBuffers is intended to be optimizable similarly to access on TypedArray views of non-growable SharedArrayBuffers, because integer-indexed property loads on are not synchronizing on the underlying buffer's length (see programmer guidelines above). For example, bounds checks for property accesses may still be hoisted out of loops.

In practice it is difficult to implement growable SharedArrayBuffer by copying on hosts that do not have virtual memory, such as those running on embedded devices without an MMU. Memory usage behaviour of growable SharedArrayBuffers on such hosts may significantly differ from that of hosts with virtual memory. Such hosts should clearly communicate memory usage expectations to users.

25.3 DataView Objects

25.3.1 Abstract Operations For DataView Objects

25.3.1.1 DataView With Buffer Witness Records

A DataView With Buffer Witness Record is a Record value used to encapsulate a DataView along with a cached byte length of the viewed buffer. It is used to help ensure there is a single shared memory read event of the byte length data block when the viewed buffer is a growable SharedArrayBuffers.

DataView With Buffer Witness Records have the fields listed in Table 77.

Table 77: DataView With Buffer Witness Record Fields
Field Name Value Meaning
[[Object]] a DataView The DataView object whose buffer's byte length is loaded.
[[CachedBufferByteLength]] a non-negative integer or detached The byte length of the object's [[ViewedArrayBuffer]] when the Record was created.

25.3.1.2 MakeDataViewWithBufferWitnessRecord ( obj, order )

The abstract operation MakeDataViewWithBufferWitnessRecord takes arguments obj (a DataView) and order (seq-cst or unordered) and returns a DataView With Buffer Witness Record. It performs the following steps when called:

  1. Let buffer be obj.[[ViewedArrayBuffer]].
  2. If IsDetachedBuffer(buffer) is true, then
    1. Let byteLength be detached.
  3. Else,
    1. Let byteLength be ArrayBufferByteLength(buffer, order).
  4. Return the DataView With Buffer Witness Record { [[Object]]: obj, [[CachedBufferByteLength]]: byteLength }.

25.3.1.3 GetViewByteLength ( viewRecord )

The abstract operation GetViewByteLength takes argument viewRecord (a DataView With Buffer Witness Record) and returns a non-negative integer. It performs the following steps when called:

  1. Assert: IsViewOutOfBounds(viewRecord) is false.
  2. Let view be viewRecord.[[Object]].
  3. If view.[[ByteLength]] is not auto, return view.[[ByteLength]].
  4. Assert: IsFixedLengthArrayBuffer(view.[[ViewedArrayBuffer]]) is false.
  5. Let byteOffset be view.[[ByteOffset]].
  6. Let byteLength be viewRecord.[[CachedBufferByteLength]].
  7. Assert: byteLength is not detached.
  8. Return byteLength - byteOffset.

25.3.1.4 IsViewOutOfBounds ( viewRecord )

The abstract operation IsViewOutOfBounds takes argument viewRecord (a DataView With Buffer Witness Record) and returns a Boolean. It performs the following steps when called:

  1. Let view be viewRecord.[[Object]].
  2. Let bufferByteLength be viewRecord.[[CachedBufferByteLength]].
  3. Assert: IsDetachedBuffer(view.[[ViewedArrayBuffer]]) is true if and only if bufferByteLength is detached.
  4. If bufferByteLength is detached, return true.
  5. Let byteOffsetStart be view.[[ByteOffset]].
  6. If view.[[ByteLength]] is auto, then
    1. Let byteOffsetEnd be bufferByteLength.
  7. Else,
    1. Let byteOffsetEnd be byteOffsetStart + view.[[ByteLength]].
  8. If byteOffsetStart > bufferByteLength or byteOffsetEnd > bufferByteLength, return true.
  9. NOTE: 0-length DataViews are not considered out-of-bounds.
  10. Return false.

25.3.1.5 GetViewValue ( view, requestIndex, isLittleEndian, type )

The abstract operation GetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), and type (a TypedArray element type) and returns either a normal completion containing either a Number or a BigInt, or a throw completion. It is used by functions on DataView instances to retrieve values from the view's buffer. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. Set isLittleEndian to ToBoolean(isLittleEndian).
  5. Let viewOffset be view.[[ByteOffset]].
  6. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  7. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  8. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  9. Let viewSize be GetViewByteLength(viewRecord).
  10. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  11. If getIndex + elementSize > viewSize, throw a RangeError exception.
  12. Let bufferIndex be getIndex + viewOffset.
  13. Return GetValueFromBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, false, unordered, isLittleEndian).

25.3.1.6 SetViewValue ( view, requestIndex, isLittleEndian, type, value )

The abstract operation SetViewValue takes arguments view (an ECMAScript language value), requestIndex (an ECMAScript language value), isLittleEndian (an ECMAScript language value), type (a TypedArray element type), and value (an ECMAScript language value) and returns either a normal completion containing undefined or a throw completion. It is used by functions on DataView instances to store values into the view's buffer. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(view, [[DataView]]).
  2. Assert: view has a [[ViewedArrayBuffer]] internal slot.
  3. Let getIndex be ? ToIndex(requestIndex).
  4. If IsBigIntElementType(type) is true, let numberValue be ? ToBigInt(value).
  5. Otherwise, let numberValue be ? ToNumber(value).
  6. Set isLittleEndian to ToBoolean(isLittleEndian).
  7. Let viewOffset be view.[[ByteOffset]].
  8. Let viewRecord be MakeDataViewWithBufferWitnessRecord(view, unordered).
  9. NOTE: Bounds checking is not a synchronizing operation when view's backing buffer is a growable SharedArrayBuffer.
  10. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  11. Let viewSize be GetViewByteLength(viewRecord).
  12. Let elementSize be the Element Size value specified in Table 75 for Element Type type.
  13. If getIndex + elementSize > viewSize, throw a RangeError exception.
  14. Let bufferIndex be getIndex + viewOffset.
  15. Perform SetValueInBuffer(view.[[ViewedArrayBuffer]], bufferIndex, type, numberValue, false, unordered, isLittleEndian).
  16. Return undefined.

25.3.2 The DataView Constructor

The DataView constructor:

  • is %DataView%.
  • is the initial value of the "DataView" property of the global object.
  • creates and initializes a new DataView when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified DataView behaviour must include a super call to the DataView constructor to create and initialize subclass instances with the internal state necessary to support the DataView.prototype built-in methods.

25.3.2.1 DataView ( buffer [ , byteOffset [ , byteLength ] ] )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Perform ? RequireInternalSlot(buffer, [[ArrayBufferData]]).
  3. Let offset be ? ToIndex(byteOffset).
  4. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  5. Let bufferByteLength be ArrayBufferByteLength(buffer, seq-cst).
  6. If offset > bufferByteLength, throw a RangeError exception.
  7. Let bufferIsFixedLength be IsFixedLengthArrayBuffer(buffer).
  8. If byteLength is undefined, then
    1. If bufferIsFixedLength is true, then
      1. Let viewByteLength be bufferByteLength - offset.
    2. Else,
      1. Let viewByteLength be auto.
  9. Else,
    1. Let viewByteLength be ? ToIndex(byteLength).
    2. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
  10. Let O be ? OrdinaryCreateFromConstructor(NewTarget, "%DataView.prototype%", « [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], [[ByteOffset]] »).
  11. If IsDetachedBuffer(buffer) is true, throw a TypeError exception.
  12. Set bufferByteLength to ArrayBufferByteLength(buffer, seq-cst).
  13. If offset > bufferByteLength, throw a RangeError exception.
  14. If byteLength is not undefined, then
    1. If offset + viewByteLength > bufferByteLength, throw a RangeError exception.
  15. Set O.[[ViewedArrayBuffer]] to buffer.
  16. Set O.[[ByteLength]] to viewByteLength.
  17. Set O.[[ByteOffset]] to offset.
  18. Return O.

25.3.3 Properties of the DataView Constructor

The DataView constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

25.3.3.1 DataView.prototype

The initial value of DataView.prototype is the DataView prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

25.3.4 Properties of the DataView Prototype Object

The DataView prototype object:

  • is %DataView.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have a [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], or [[ByteOffset]] internal slot.

25.3.4.1 get DataView.prototype.buffer

DataView.prototype.buffer is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[DataView]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. Let buffer be O.[[ViewedArrayBuffer]].
  5. Return buffer.

25.3.4.2 get DataView.prototype.byteLength

DataView.prototype.byteLength is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[DataView]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. Let viewRecord be MakeDataViewWithBufferWitnessRecord(O, seq-cst).
  5. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  6. Let size be GetViewByteLength(viewRecord).
  7. Return 𝔽(size).

25.3.4.3 get DataView.prototype.byteOffset

DataView.prototype.byteOffset is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[DataView]]).
  3. Assert: O has a [[ViewedArrayBuffer]] internal slot.
  4. Let viewRecord be MakeDataViewWithBufferWitnessRecord(O, seq-cst).
  5. If IsViewOutOfBounds(viewRecord) is true, throw a TypeError exception.
  6. Let offset be O.[[ByteOffset]].
  7. Return 𝔽(offset).

25.3.4.4 DataView.prototype.constructor

The initial value of DataView.prototype.constructor is %DataView%.

25.3.4.5 DataView.prototype.getBigInt64 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? GetViewValue(view, byteOffset, littleEndian, bigint64).

25.3.4.6 DataView.prototype.getBigUint64 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? GetViewValue(view, byteOffset, littleEndian, biguint64).

25.3.4.7 DataView.prototype.getFloat16 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, float16).

25.3.4.8 DataView.prototype.getFloat32 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, float32).

25.3.4.9 DataView.prototype.getFloat64 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, float64).

25.3.4.10 DataView.prototype.getInt8 ( byteOffset )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? GetViewValue(view, byteOffset, true, int8).

25.3.4.11 DataView.prototype.getInt16 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, int16).

25.3.4.12 DataView.prototype.getInt32 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, int32).

25.3.4.13 DataView.prototype.getUint8 ( byteOffset )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? GetViewValue(view, byteOffset, true, uint8).

25.3.4.14 DataView.prototype.getUint16 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, uint16).

25.3.4.15 DataView.prototype.getUint32 ( byteOffset [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? GetViewValue(view, byteOffset, littleEndian, uint32).

25.3.4.16 DataView.prototype.setBigInt64 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? SetViewValue(view, byteOffset, littleEndian, bigint64, value).

25.3.4.17 DataView.prototype.setBigUint64 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? SetViewValue(view, byteOffset, littleEndian, biguint64, value).

25.3.4.18 DataView.prototype.setFloat16 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, float16, value).

25.3.4.19 DataView.prototype.setFloat32 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, float32, value).

25.3.4.20 DataView.prototype.setFloat64 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, float64, value).

25.3.4.21 DataView.prototype.setInt8 ( byteOffset, value )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? SetViewValue(view, byteOffset, true, int8, value).

25.3.4.22 DataView.prototype.setInt16 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, int16, value).

25.3.4.23 DataView.prototype.setInt32 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, int32, value).

25.3.4.24 DataView.prototype.setUint8 ( byteOffset, value )

This method performs the following steps when called:

  1. Let view be the this value.
  2. Return ? SetViewValue(view, byteOffset, true, uint8, value).

25.3.4.25 DataView.prototype.setUint16 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, uint16, value).

25.3.4.26 DataView.prototype.setUint32 ( byteOffset, value [ , littleEndian ] )

This method performs the following steps when called:

  1. Let view be the this value.
  2. If littleEndian is not present, set littleEndian to false.
  3. Return ? SetViewValue(view, byteOffset, littleEndian, uint32, value).

25.3.4.27 DataView.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "DataView".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

25.3.5 Properties of DataView Instances

DataView instances are ordinary objects that inherit properties from the DataView prototype object. DataView instances each have [[DataView]], [[ViewedArrayBuffer]], [[ByteLength]], and [[ByteOffset]] internal slots.

Note

The value of the [[DataView]] internal slot is not used within this specification. The simple presence of that internal slot is used within the specification to identify objects created using the DataView constructor.

25.4 The Atomics Object

The Atomics object:

  • is %Atomics%.
  • is the initial value of the "Atomics" property of the global object.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • does not have a [[Construct]] internal method; it cannot be used as a constructor with the new operator.
  • does not have a [[Call]] internal method; it cannot be invoked as a function.

The Atomics object provides functions that operate indivisibly (atomically) on shared memory array cells as well as functions that let agents wait for and dispatch primitive events. When used with discipline, the Atomics functions allow multi-agent programs that communicate through shared memory to execute in a well-understood order even on parallel CPUs. The rules that govern shared-memory communication are provided by the memory model, defined below.

Note

For informative guidelines for programming and implementing shared memory in ECMAScript, please see the notes at the end of the memory model section.

25.4.1 Waiter Record

A Waiter Record is a Record value used to denote a particular call to Atomics.wait or Atomics.waitAsync.

A Waiter Record has fields listed in Table 78.

Table 78: Waiter Record Fields
Field Name Value Meaning
[[AgentSignifier]] an agent signifier The agent that called Atomics.wait or Atomics.waitAsync.
[[PromiseCapability]] a PromiseCapability Record or blocking If denoting a call to Atomics.waitAsync, the resulting promise, otherwise blocking.
[[TimeoutTime]] a non-negative extended mathematical value The earliest time by which timeout may be triggered; computed using time values.
[[Result]] "ok" or "timed-out" The return value of the call.

25.4.2 WaiterList Records

A WaiterList Record is used to explain waiting and notification of agents via Atomics.wait, Atomics.waitAsync, and Atomics.notify.

A WaiterList Record has fields listed in Table 79.

Table 79: WaiterList Record Fields
Field Name Value Meaning
[[Waiters]] a List of Waiter Records The calls to Atomics.wait or Atomics.waitAsync that are waiting on the location with which this WaiterList is associated.
[[MostRecentLeaveEvent]] a Synchronize event or empty The event of the most recent leaving of its critical section, or empty if its critical section has never been entered.

There can be multiple Waiter Records in a WaiterList with the same agent signifier.

The agent cluster has a store of WaiterList Records; the store is indexed by (block, i), where block is a Shared Data Block and i a byte offset into the memory of block. WaiterList Records are agent-independent: a lookup in the store of WaiterList Records by (block, i) will result in the same WaiterList Record in any agent in the agent cluster.

Each WaiterList Record has a critical section that controls exclusive access to that WaiterList Record during evaluation. Only a single agent may enter a WaiterList Record's critical section at one time. Entering and leaving a WaiterList Record's critical section is controlled by the abstract operations EnterCriticalSection and LeaveCriticalSection. Operations on a WaiterList Record—adding and removing waiting agents, traversing the list of agents, suspending and notifying agents on the list, setting and retrieving the Synchronize event—may only be performed by agents that have entered the WaiterList Record's critical section.

25.4.3 Abstract Operations for Atomics

25.4.3.1 ValidateIntegerTypedArray ( typedArray, waitable )

The abstract operation ValidateIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and waitable (a Boolean) and returns either a normal completion containing a TypedArray With Buffer Witness Record, or a throw completion. It performs the following steps when called:

  1. Let taRecord be ? ValidateTypedArray(typedArray, unordered).
  2. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  3. If waitable is true, then
    1. If typedArray.[[TypedArrayName]] is neither "Int32Array" nor "BigInt64Array", throw a TypeError exception.
  4. Else,
    1. Let type be TypedArrayElementType(typedArray).
    2. If IsUnclampedIntegerElementType(type) is false and IsBigIntElementType(type) is false, throw a TypeError exception.
  5. Return taRecord.

25.4.3.2 ValidateAtomicAccess ( taRecord, requestIndex )

The abstract operation ValidateAtomicAccess takes arguments taRecord (a TypedArray With Buffer Witness Record) and requestIndex (an ECMAScript language value) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

  1. Let length be TypedArrayLength(taRecord).
  2. Let accessIndex be ? ToIndex(requestIndex).
  3. Assert: accessIndex ≥ 0.
  4. If accessIndexlength, throw a RangeError exception.
  5. Let typedArray be taRecord.[[Object]].
  6. Let elementSize be TypedArrayElementSize(typedArray).
  7. Let offset be typedArray.[[ByteOffset]].
  8. Return (accessIndex × elementSize) + offset.

25.4.3.3 ValidateAtomicAccessOnIntegerTypedArray ( typedArray, requestIndex )

The abstract operation ValidateAtomicAccessOnIntegerTypedArray takes arguments typedArray (an ECMAScript language value) and requestIndex (an ECMAScript language value) and returns either a normal completion containing an integer or a throw completion. It performs the following steps when called:

  1. Let taRecord be ? ValidateIntegerTypedArray(typedArray, false).
  2. Return ? ValidateAtomicAccess(taRecord, requestIndex).

25.4.3.4 RevalidateAtomicAccess ( typedArray, byteIndexInBuffer )

The abstract operation RevalidateAtomicAccess takes arguments typedArray (a TypedArray) and byteIndexInBuffer (an integer) and returns either a normal completion containing unused or a throw completion. This operation revalidates the index within the backing buffer for atomic operations after all argument coercions are performed in Atomics methods, as argument coercions can have arbitrary side effects, which could cause the buffer to become out of bounds. This operation does not throw when typedArray's backing buffer is a SharedArrayBuffer. It performs the following steps when called:

  1. Let taRecord be MakeTypedArrayWithBufferWitnessRecord(typedArray, unordered).
  2. NOTE: Bounds checking is not a synchronizing operation when typedArray's backing buffer is a growable SharedArrayBuffer.
  3. If IsTypedArrayOutOfBounds(taRecord) is true, throw a TypeError exception.
  4. Assert: byteIndexInBuffertypedArray.[[ByteOffset]].
  5. If byteIndexInBuffertaRecord.[[CachedBufferByteLength]], throw a RangeError exception.
  6. Return unused.

25.4.3.5 GetWaiterList ( block, i )

The abstract operation GetWaiterList takes arguments block (a Shared Data Block) and i (a non-negative integer that is evenly divisible by 4) and returns a WaiterList Record. It performs the following steps when called:

  1. Assert: i and i + 3 are valid byte offsets within the memory of block.
  2. Return the WaiterList Record that is referenced by the pair (block, i).

25.4.3.6 EnterCriticalSection ( WL )

The abstract operation EnterCriticalSection takes argument WL (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is not in the critical section for any WaiterList Record.
  2. Wait until no agent is in the critical section for WL, then enter the critical section for WL (without allowing any other agent to enter).
  3. If WL.[[MostRecentLeaveEvent]] is not empty, then
    1. NOTE: A WL whose critical section has been entered at least once has a Synchronize event set by LeaveCriticalSection.
    2. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
    3. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
    4. Let enterEvent be a new Synchronize event.
    5. Append enterEvent to eventsRecord.[[EventList]].
    6. Append (WL.[[MostRecentLeaveEvent]], enterEvent) to eventsRecord.[[AgentSynchronizesWith]].
  4. Return unused.

EnterCriticalSection has contention when an agent attempting to enter the critical section must wait for another agent to leave it. When there is no contention, FIFO order of EnterCriticalSection calls is observable. When there is contention, an implementation may choose an arbitrary order but may not cause an agent to wait indefinitely.

25.4.3.7 LeaveCriticalSection ( WL )

The abstract operation LeaveCriticalSection takes argument WL (a WaiterList Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
  3. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
  4. Let leaveEvent be a new Synchronize event.
  5. Append leaveEvent to eventsRecord.[[EventList]].
  6. Set WL.[[MostRecentLeaveEvent]] to leaveEvent.
  7. Leave the critical section for WL.
  8. Return unused.

25.4.3.8 AddWaiter ( WL, waiterRecord )

The abstract operation AddWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. Assert: There is no Waiter Record in WL.[[Waiters]] whose [[PromiseCapability]] field is waiterRecord.[[PromiseCapability]] and whose [[AgentSignifier]] field is waiterRecord.[[AgentSignifier]].
  3. Append waiterRecord to WL.[[Waiters]].
  4. Return unused.

25.4.3.9 RemoveWaiter ( WL, waiterRecord )

The abstract operation RemoveWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. Assert: WL.[[Waiters]] contains waiterRecord.
  3. Remove waiterRecord from WL.[[Waiters]].
  4. Return unused.

25.4.3.10 RemoveWaiters ( WL, c )

The abstract operation RemoveWaiters takes arguments WL (a WaiterList Record) and c (a non-negative integer or +∞) and returns a List of Waiter Records. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. Let len be the number of elements in WL.[[Waiters]].
  3. Let n be min(c, len).
  4. Let L be a List whose elements are the first n elements of WL.[[Waiters]].
  5. Remove the first n elements of WL.[[Waiters]].
  6. Return L.

25.4.3.11 SuspendThisAgent ( WL, waiterRecord )

The abstract operation SuspendThisAgent takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. Assert: WL.[[Waiters]] contains waiterRecord.
  3. Let thisAgent be AgentSignifier().
  4. Assert: waiterRecord.[[AgentSignifier]] is thisAgent.
  5. Assert: waiterRecord.[[PromiseCapability]] is blocking.
  6. Assert: AgentCanSuspend() is true.
  7. Perform LeaveCriticalSection(WL) and suspend the surrounding agent until the time is waiterRecord.[[TimeoutTime]], performing the combined operation in such a way that a notification that arrives after the critical section is exited but before the suspension takes effect is not lost. The surrounding agent can only wake from suspension due to a timeout or due to another agent calling NotifyWaiter with arguments WL and thisAgent (i.e. via a call to Atomics.notify).
  8. Perform EnterCriticalSection(WL).
  9. Return unused.

25.4.3.12 NotifyWaiter ( WL, waiterRecord )

The abstract operation NotifyWaiter takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. Assert: The surrounding agent is in the critical section for WL.
  2. If waiterRecord.[[PromiseCapability]] is blocking, then
    1. Wake the agent whose signifier is waiterRecord.[[AgentSignifier]] from suspension.
    2. NOTE: This causes the agent to resume execution in SuspendThisAgent.
  3. Else if AgentSignifier() is waiterRecord.[[AgentSignifier]], then
    1. Let promiseCapability be waiterRecord.[[PromiseCapability]].
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « waiterRecord.[[Result]] »).
  4. Else,
    1. Perform EnqueueResolveInAgentJob(waiterRecord.[[AgentSignifier]], waiterRecord.[[PromiseCapability]], waiterRecord.[[Result]]).
  5. Return unused.
Note

An agent must not access another agent's promise capability in any capacity beyond passing it to the host.

25.4.3.13 EnqueueResolveInAgentJob ( agentSignifier, promiseCapability, resolution )

The abstract operation EnqueueResolveInAgentJob takes arguments agentSignifier (an agent signifier), promiseCapability (a PromiseCapability Record), and resolution ("ok" or "timed-out") and returns unused. It performs the following steps when called:

  1. Let resolveJob be a new Job Abstract Closure with no parameters that captures agentSignifier, promiseCapability, and resolution and performs the following steps when called:
    1. Assert: AgentSignifier() is agentSignifier.
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « resolution »).
    3. Return unused.
  2. Let realmInTargetAgent be ! GetFunctionRealm(promiseCapability.[[Resolve]]).
  3. Assert: agentSignifier is realmInTargetAgent.[[AgentSignifier]].
  4. Perform HostEnqueueGenericJob(resolveJob, realmInTargetAgent).
  5. Return unused.

25.4.3.14 DoWait ( mode, typedArray, index, value, timeout )

The abstract operation DoWait takes arguments mode (sync or async), typedArray (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and timeout (an ECMAScript language value) and returns either a normal completion containing either an Object, "not-equal", "timed-out", or "ok", or a throw completion. It performs the following steps when called:

  1. Let taRecord be ? ValidateIntegerTypedArray(typedArray, true).
  2. Let buffer be taRecord.[[Object]].[[ViewedArrayBuffer]].
  3. If IsSharedArrayBuffer(buffer) is false, throw a TypeError exception.
  4. Let i be ? ValidateAtomicAccess(taRecord, index).
  5. Let arrayTypeName be typedArray.[[TypedArrayName]].
  6. If arrayTypeName is "BigInt64Array", let v be ? ToBigInt64(value).
  7. Else, let v be ? ToInt32(value).
  8. Let q be ? ToNumber(timeout).
  9. If q is either NaN or +∞𝔽, let t be +∞; else if q is -∞𝔽, let t be 0; else let t be max((q), 0).
  10. If mode is sync and AgentCanSuspend() is false, throw a TypeError exception.
  11. Let block be buffer.[[ArrayBufferData]].
  12. Let offset be typedArray.[[ByteOffset]].
  13. Let byteIndexInBuffer be (i × 4) + offset.
  14. Let WL be GetWaiterList(block, byteIndexInBuffer).
  15. If mode is sync, then
    1. Let promiseCapability be blocking.
    2. Let resultObject be undefined.
  16. Else,
    1. Let promiseCapability be ! NewPromiseCapability(%Promise%).
    2. Let resultObject be OrdinaryObjectCreate(%Object.prototype%).
  17. Perform EnterCriticalSection(WL).
  18. Let elementType be TypedArrayElementType(typedArray).
  19. Let w be GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst).
  20. If vw, then
    1. Perform LeaveCriticalSection(WL).
    2. If mode is sync, return "not-equal".
    3. Perform ! CreateDataPropertyOrThrow(resultObject, "async", false).
    4. Perform ! CreateDataPropertyOrThrow(resultObject, "value", "not-equal").
    5. Return resultObject.
  21. If t = 0 and mode is async, then
    1. NOTE: There is no special handling of synchronous immediate timeouts. Asynchronous immediate timeouts have special handling in order to fail fast and avoid unnecessary Promise jobs.
    2. Perform LeaveCriticalSection(WL).
    3. Perform ! CreateDataPropertyOrThrow(resultObject, "async", false).
    4. Perform ! CreateDataPropertyOrThrow(resultObject, "value", "timed-out").
    5. Return resultObject.
  22. Let thisAgent be AgentSignifier().
  23. Let now be the time value (UTC) identifying the current time.
  24. Let additionalTimeout be an implementation-defined non-negative mathematical value.
  25. Let timeoutTime be (now) + t + additionalTimeout.
  26. NOTE: When t is +∞, timeoutTime is also +∞.
  27. Let waiterRecord be a new Waiter Record { [[AgentSignifier]]: thisAgent, [[PromiseCapability]]: promiseCapability, [[TimeoutTime]]: timeoutTime, [[Result]]: "ok" }.
  28. Perform AddWaiter(WL, waiterRecord).
  29. If mode is sync, then
    1. Perform SuspendThisAgent(WL, waiterRecord).
  30. Else if timeoutTime is finite, then
    1. Perform EnqueueAtomicsWaitAsyncTimeoutJob(WL, waiterRecord).
  31. Perform LeaveCriticalSection(WL).
  32. If mode is sync, return waiterRecord.[[Result]].
  33. Perform ! CreateDataPropertyOrThrow(resultObject, "async", true).
  34. Perform ! CreateDataPropertyOrThrow(resultObject, "value", promiseCapability.[[Promise]]).
  35. Return resultObject.
Note

additionalTimeout allows implementations to pad timeouts as necessary, such as for reducing power consumption or coarsening timer resolution to mitigate timing attacks. This value may differ from call to call of DoWait.

25.4.3.15 EnqueueAtomicsWaitAsyncTimeoutJob ( WL, waiterRecord )

The abstract operation EnqueueAtomicsWaitAsyncTimeoutJob takes arguments WL (a WaiterList Record) and waiterRecord (a Waiter Record) and returns unused. It performs the following steps when called:

  1. Let timeoutJob be a new Job Abstract Closure with no parameters that captures WL and waiterRecord and performs the following steps when called:
    1. Perform EnterCriticalSection(WL).
    2. If WL.[[Waiters]] contains waiterRecord, then
      1. Let timeOfJobExecution be the time value (UTC) identifying the current time.
      2. Assert: (timeOfJobExecution) ≥ waiterRecord.[[TimeoutTime]] (ignoring potential non-monotonicity of time values).
      3. Set waiterRecord.[[Result]] to "timed-out".
      4. Perform RemoveWaiter(WL, waiterRecord).
      5. Perform NotifyWaiter(WL, waiterRecord).
    3. Perform LeaveCriticalSection(WL).
    4. Return unused.
  2. Let now be the time value (UTC) identifying the current time.
  3. Let currentRealm be the current Realm Record.
  4. Perform HostEnqueueTimeoutJob(timeoutJob, currentRealm, 𝔽(waiterRecord.[[TimeoutTime]]) - now).
  5. Return unused.

25.4.3.16 AtomicCompareExchangeInSharedBlock ( block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes )

The abstract operation AtomicCompareExchangeInSharedBlock takes arguments block (a Shared Data Block), byteIndexInBuffer (an integer), elementSize (a non-negative integer), expectedBytes (a List of byte values), and replacementBytes (a List of byte values) and returns a List of byte values. It performs the following steps when called:

  1. Let execution be the [[CandidateExecution]] field of the surrounding agent's Agent Record.
  2. Let eventsRecord be the Agent Events Record of execution.[[EventsRecords]] whose [[AgentSignifier]] is AgentSignifier().
  3. Let rawBytesRead be a List of length elementSize whose elements are nondeterministically chosen byte values.
  4. NOTE: In implementations, rawBytesRead is the result of a load-link, of a load-exclusive, or of an operand of a read-modify-write instruction on the underlying hardware. The nondeterminism is a semantic prescription of the memory model to describe observable behaviour of hardware with weak consistency.
  5. NOTE: The comparison of the expected value and the read value is performed outside of the read-modify-write modification function to avoid needlessly strong synchronization when the expected value is not equal to the read value.
  6. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
    1. Let second be a new read-modify-write modification function with parameters (oldBytes, newBytes) that captures nothing and performs the following steps atomically when called:
      1. Return newBytes.
    2. Let event be ReadModifyWriteSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize, [[Payload]]: replacementBytes, [[ModifyOp]]: second }.
  7. Else,
    1. Let event be ReadSharedMemory { [[Order]]: seq-cst, [[NoTear]]: true, [[Block]]: block, [[ByteIndex]]: byteIndexInBuffer, [[ElementSize]]: elementSize }.
  8. Append event to eventsRecord.[[EventList]].
  9. Append Chosen Value Record { [[Event]]: event, [[ChosenValue]]: rawBytesRead } to execution.[[ChosenValues]].
  10. Return rawBytesRead.

25.4.3.17 AtomicReadModifyWrite ( typedArray, index, value, op )

The abstract operation AtomicReadModifyWrite takes arguments typedArray (an ECMAScript language value), index (an ECMAScript language value), value (an ECMAScript language value), and op (a read-modify-write modification function) and returns either a normal completion containing either a Number or a BigInt, or a throw completion. op takes two List of byte values arguments and returns a List of byte values. This operation atomically loads a value, combines it with another value, and stores the combination. It returns the loaded value. It performs the following steps when called:

  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Return GetModifySetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, op).

25.4.3.18 ByteListBitwiseOp ( op, xBytes, yBytes )

The abstract operation ByteListBitwiseOp takes arguments op (&, ^, or |), xBytes (a List of byte values), and yBytes (a List of byte values) and returns a List of byte values. The operation atomically performs a bitwise operation on all byte values of the arguments and returns a List of byte values. It performs the following steps when called:

  1. Assert: xBytes and yBytes have the same number of elements.
  2. Let result be a new empty List.
  3. Let i be 0.
  4. For each element xByte of xBytes, do
    1. Let yByte be yBytes[i].
    2. If op is &, then
      1. Let resultByte be the result of applying the bitwise AND operation to xByte and yByte.
    3. Else if op is ^, then
      1. Let resultByte be the result of applying the bitwise exclusive OR (XOR) operation to xByte and yByte.
    4. Else,
      1. Assert: op is |.
      2. Let resultByte be the result of applying the bitwise inclusive OR operation to xByte and yByte.
    5. Set i to i + 1.
    6. Append resultByte to result.
  5. Return result.

25.4.3.19 ByteListEqual ( xBytes, yBytes )

The abstract operation ByteListEqual takes arguments xBytes (a List of byte values) and yBytes (a List of byte values) and returns a Boolean. It performs the following steps when called:

  1. If xBytes and yBytes do not have the same number of elements, return false.
  2. Let i be 0.
  3. For each element xByte of xBytes, do
    1. Let yByte be yBytes[i].
    2. If xByteyByte, return false.
    3. Set i to i + 1.
  4. Return true.

25.4.4 Atomics.add ( typedArray, index, value )

This function performs the following steps when called:

  1. Let add be a new read-modify-write modification function with parameters (xBytes, yBytes) that captures typedArray and performs the following steps atomically when called:
    1. Let type be TypedArrayElementType(typedArray).
    2. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
    3. Let x be RawBytesToNumeric(type, xBytes, isLittleEndian).
    4. Let y be RawBytesToNumeric(type, yBytes, isLittleEndian).
    5. If x is a Number, then
      1. Let sum be Number::add(x, y).
    6. Else,
      1. Assert: x is a BigInt.
      2. Let sum be BigInt::add(x, y).
    7. Let sumBytes be NumericToRawBytes(type, sum, isLittleEndian).
    8. Assert: sumBytes, xBytes, and yBytes have the same number of elements.
    9. Return sumBytes.
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, add).

25.4.5 Atomics.and ( typedArray, index, value )

This function performs the following steps when called:

  1. Let and be a new read-modify-write modification function with parameters (xBytes, yBytes) that captures nothing and performs the following steps atomically when called:
    1. Return ByteListBitwiseOp(&, xBytes, yBytes).
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, and).

25.4.6 Atomics.compareExchange ( typedArray, index, expectedValue, replacementValue )

This function performs the following steps when called:

  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index).
  2. Let buffer be typedArray.[[ViewedArrayBuffer]].
  3. Let block be buffer.[[ArrayBufferData]].
  4. If typedArray.[[ContentType]] is bigint, then
    1. Let expected be ? ToBigInt(expectedValue).
    2. Let replacement be ? ToBigInt(replacementValue).
  5. Else,
    1. Let expected be 𝔽(? ToIntegerOrInfinity(expectedValue)).
    2. Let replacement be 𝔽(? ToIntegerOrInfinity(replacementValue)).
  6. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  7. Let elementType be TypedArrayElementType(typedArray).
  8. Let elementSize be TypedArrayElementSize(typedArray).
  9. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
  10. Let expectedBytes be NumericToRawBytes(elementType, expected, isLittleEndian).
  11. Let replacementBytes be NumericToRawBytes(elementType, replacement, isLittleEndian).
  12. If IsSharedArrayBuffer(buffer) is true, then
    1. Let rawBytesRead be AtomicCompareExchangeInSharedBlock(block, byteIndexInBuffer, elementSize, expectedBytes, replacementBytes).
  13. Else,
    1. Let rawBytesRead be a List of length elementSize whose elements are the sequence of elementSize bytes starting with block[byteIndexInBuffer].
    2. If ByteListEqual(rawBytesRead, expectedBytes) is true, then
      1. Store the individual bytes of replacementBytes into block, starting at block[byteIndexInBuffer].
  14. Return RawBytesToNumeric(elementType, rawBytesRead, isLittleEndian).

25.4.7 Atomics.exchange ( typedArray, index, value )

This function performs the following steps when called:

  1. Let second be a new read-modify-write modification function with parameters (oldBytes, newBytes) that captures nothing and performs the following steps atomically when called:
    1. Return newBytes.
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, second).

25.4.8 Atomics.isLockFree ( size )

This function performs the following steps when called:

  1. Let n be ? ToIntegerOrInfinity(size).
  2. Let AR be the Agent Record of the surrounding agent.
  3. If n = 1, return AR.[[IsLockFree1]].
  4. If n = 2, return AR.[[IsLockFree2]].
  5. If n = 4, return true.
  6. If n = 8, return AR.[[IsLockFree8]].
  7. Return false.
Note

This function is an optimization primitive. The intuition is that if the atomic step of an atomic primitive (compareExchange, load, store, add, sub, and, or, xor, or exchange) on a datum of size n bytes will be performed without the surrounding agent acquiring a lock outside the n bytes comprising the datum, then Atomics.isLockFree(n) will return true. High-performance algorithms will use this function to determine whether to use locks or atomic operations in critical sections. If an atomic primitive is not lock-free then it is often more efficient for an algorithm to provide its own locking.

Atomics.isLockFree(4) always returns true as that can be supported on all known relevant hardware. Being able to assume this will generally simplify programs.

Regardless of the value returned by this function, all atomic operations are guaranteed to be atomic. For example, they will never have a visible operation take place in the middle of the operation (e.g., "tearing").

25.4.9 Atomics.load ( typedArray, index )

This function performs the following steps when called:

  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index).
  2. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  3. Let buffer be typedArray.[[ViewedArrayBuffer]].
  4. Let elementType be TypedArrayElementType(typedArray).
  5. Return GetValueFromBuffer(buffer, byteIndexInBuffer, elementType, true, seq-cst).

25.4.10 Atomics.or ( typedArray, index, value )

This function performs the following steps when called:

  1. Let or be a new read-modify-write modification function with parameters (xBytes, yBytes) that captures nothing and performs the following steps atomically when called:
    1. Return ByteListBitwiseOp(|, xBytes, yBytes).
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, or).

25.4.11 Atomics.store ( typedArray, index, value )

This function performs the following steps when called:

  1. Let byteIndexInBuffer be ? ValidateAtomicAccessOnIntegerTypedArray(typedArray, index).
  2. If typedArray.[[ContentType]] is bigint, let v be ? ToBigInt(value).
  3. Otherwise, let v be 𝔽(? ToIntegerOrInfinity(value)).
  4. Perform ? RevalidateAtomicAccess(typedArray, byteIndexInBuffer).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let elementType be TypedArrayElementType(typedArray).
  7. Perform SetValueInBuffer(buffer, byteIndexInBuffer, elementType, v, true, seq-cst).
  8. Return v.

25.4.12 Atomics.sub ( typedArray, index, value )

This function performs the following steps when called:

  1. Let subtract be a new read-modify-write modification function with parameters (xBytes, yBytes) that captures typedArray and performs the following steps atomically when called:
    1. Let type be TypedArrayElementType(typedArray).
    2. Let isLittleEndian be the value of the [[LittleEndian]] field of the surrounding agent's Agent Record.
    3. Let x be RawBytesToNumeric(type, xBytes, isLittleEndian).
    4. Let y be RawBytesToNumeric(type, yBytes, isLittleEndian).
    5. If x is a Number, then
      1. Let difference be Number::subtract(x, y).
    6. Else,
      1. Assert: x is a BigInt.
      2. Let difference be BigInt::subtract(x, y).
    7. Let differenceBytes be NumericToRawBytes(type, difference, isLittleEndian).
    8. Assert: differenceBytes, xBytes, and yBytes have the same number of elements.
    9. Return differenceBytes.
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, subtract).

25.4.13 Atomics.wait ( typedArray, index, value, timeout )

This function puts the surrounding agent in a wait queue and suspends it until notified or until the wait times out, returning a String differentiating those cases.

It performs the following steps when called:

  1. Return ? DoWait(sync, typedArray, index, value, timeout).

25.4.14 Atomics.waitAsync ( typedArray, index, value, timeout )

This function returns a Promise that is resolved when the calling agent is notified or the timeout is reached.

It performs the following steps when called:

  1. Return ? DoWait(async, typedArray, index, value, timeout).

25.4.15 Atomics.notify ( typedArray, index, count )

This function notifies some agents that are sleeping in the wait queue.

It performs the following steps when called:

  1. Let taRecord be ? ValidateIntegerTypedArray(typedArray, true).
  2. Let byteIndexInBuffer be ? ValidateAtomicAccess(taRecord, index).
  3. If count is undefined, then
    1. Let c be +∞.
  4. Else,
    1. Let intCount be ? ToIntegerOrInfinity(count).
    2. Let c be max(intCount, 0).
  5. Let buffer be typedArray.[[ViewedArrayBuffer]].
  6. Let block be buffer.[[ArrayBufferData]].
  7. If IsSharedArrayBuffer(buffer) is false, return +0𝔽.
  8. Let WL be GetWaiterList(block, byteIndexInBuffer).
  9. Perform EnterCriticalSection(WL).
  10. Let S be RemoveWaiters(WL, c).
  11. For each element W of S, do
    1. Perform NotifyWaiter(WL, W).
  12. Perform LeaveCriticalSection(WL).
  13. Let n be the number of elements in S.
  14. Return 𝔽(n).

25.4.16 Atomics.xor ( typedArray, index, value )

This function performs the following steps when called:

  1. Let xor be a new read-modify-write modification function with parameters (xBytes, yBytes) that captures nothing and performs the following steps atomically when called:
    1. Return ByteListBitwiseOp(^, xBytes, yBytes).
  2. Return ? AtomicReadModifyWrite(typedArray, index, value, xor).

25.4.17 Atomics [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "Atomics".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

25.5 The JSON Object

The JSON object:

  • is %JSON%.
  • is the initial value of the "JSON" property of the global object.
  • is an ordinary object.
  • contains two functions, parse and stringify, that are used to parse and construct JSON texts.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • does not have a [[Construct]] internal method; it cannot be used as a constructor with the new operator.
  • does not have a [[Call]] internal method; it cannot be invoked as a function.

The JSON Data Interchange Format is defined in ECMA-404. The JSON interchange format used in this specification is exactly that described by ECMA-404. Conforming implementations of JSON.parse and JSON.stringify must support the exact interchange format described in the ECMA-404 specification without any deletions or extensions to the format.

25.5.1 JSON.parse ( text [ , reviver ] )

This function parses a JSON text (a JSON-formatted String) and produces an ECMAScript language value. The JSON format represents literals, arrays, and objects with a syntax similar to the syntax for ECMAScript literals, Array Initializers, and Object Initializers. After parsing, JSON objects are realized as ECMAScript objects. JSON arrays are realized as ECMAScript Array instances. JSON strings, numbers, booleans, and null are realized as ECMAScript Strings, Numbers, Booleans, and null.

The optional reviver parameter is a function that takes two parameters, key and value. It can filter and transform the results. It is called with each of the key/value pairs produced by the parse, and its return value is used instead of the original value. If it returns what it received, the structure is not modified. If it returns undefined then the property is deleted from the result.

  1. Let jsonString be ? ToString(text).
  2. Let unfiltered be ? ParseJSON(jsonString).
  3. If IsCallable(reviver) is true, then
    1. Let root be OrdinaryObjectCreate(%Object.prototype%).
    2. Let rootName be the empty String.
    3. Perform ! CreateDataPropertyOrThrow(root, rootName, unfiltered).
    4. Return ? InternalizeJSONProperty(root, rootName, reviver).
  4. Else,
    1. Return unfiltered.

The "length" property of this function is 2𝔽.

25.5.1.1 ParseJSON ( text )

The abstract operation ParseJSON takes argument text (a String) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. If StringToCodePoints(text) is not a valid JSON text as specified in ECMA-404, throw a SyntaxError exception.
  2. Let scriptString be the string-concatenation of "(", text, and ");".
  3. Let script be ParseText(scriptString, Script).
  4. NOTE: The early error rules defined in 13.2.5.1 have special handling for the above invocation of ParseText.
  5. Assert: script is a Parse Node.
  6. Let result be ! Evaluation of script.
  7. NOTE: The PropertyDefinitionEvaluation semantics defined in 13.2.5.5 have special handling for the above evaluation.
  8. Assert: result is either a String, a Number, a Boolean, an Object that is defined by either an ArrayLiteral or an ObjectLiteral, or null.
  9. Return result.

It is not permitted for a conforming implementation of JSON.parse to extend the JSON grammars. If an implementation wishes to support a modified or extended JSON interchange format it must do so by defining a different parse function.

Note 1

Valid JSON text is a subset of the ECMAScript PrimaryExpression syntax. Step 1 verifies that jsonString conforms to that subset, and step 8 asserts that evaluation returns a value of an appropriate type.

However, because 13.2.5.5 behaves differently during ParseJSON, the same source text can produce different results when evaluated as a PrimaryExpression rather than as JSON. Furthermore, the Early Error for duplicate "__proto__" properties in object literals, which likewise does not apply during ParseJSON, means that not all texts accepted by ParseJSON are valid as a PrimaryExpression, despite matching the grammar.

Note 2

In the case where there are duplicate name Strings within an object, lexically preceding values for the same key shall be overwritten.

25.5.1.2 InternalizeJSONProperty ( holder, name, reviver )

The abstract operation InternalizeJSONProperty takes arguments holder (an Object), name (a String), and reviver (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion.

Note

This algorithm intentionally does not throw an exception if either [[Delete]] or CreateDataProperty return false.

It performs the following steps when called:

  1. Let val be ? Get(holder, name).
  2. If val is an Object, then
    1. Let isArray be ? IsArray(val).
    2. If isArray is true, then
      1. Let len be ? LengthOfArrayLike(val).
      2. Let I be 0.
      3. Repeat, while I < len,
        1. Let prop be ! ToString(𝔽(I)).
        2. Let newElement be ? InternalizeJSONProperty(val, prop, reviver).
        3. If newElement is undefined, then
          1. Perform ? val.[[Delete]](prop).
        4. Else,
          1. Perform ? CreateDataProperty(val, prop, newElement).
        5. Set I to I + 1.
    3. Else,
      1. Let keys be ? EnumerableOwnProperties(val, key).
      2. For each String P of keys, do
        1. Let newElement be ? InternalizeJSONProperty(val, P, reviver).
        2. If newElement is undefined, then
          1. Perform ? val.[[Delete]](P).
        3. Else,
          1. Perform ? CreateDataProperty(val, P, newElement).
  3. Return ? Call(reviver, holder, « name, val »).

25.5.2 JSON.stringify ( value [ , replacer [ , space ] ] )

This function returns a String in UTF-16 encoded JSON format representing an ECMAScript language value, or undefined. It can take three parameters. The value parameter is an ECMAScript language value, which is usually an object or array, although it can also be a String, Boolean, Number or null. The optional replacer parameter is either a function that alters the way objects and arrays are stringified, or an array of Strings and Numbers that acts as an inclusion list for selecting the object properties that will be stringified. The optional space parameter is a String or Number that allows the result to have white space injected into it to improve human readability.

It performs the following steps when called:

  1. Let stack be a new empty List.
  2. Let indent be the empty String.
  3. Let PropertyList be undefined.
  4. Let ReplacerFunction be undefined.
  5. If replacer is an Object, then
    1. If IsCallable(replacer) is true, then
      1. Set ReplacerFunction to replacer.
    2. Else,
      1. Let isArray be ? IsArray(replacer).
      2. If isArray is true, then
        1. Set PropertyList to a new empty List.
        2. Let len be ? LengthOfArrayLike(replacer).
        3. Let k be 0.
        4. Repeat, while k < len,
          1. Let prop be ! ToString(𝔽(k)).
          2. Let v be ? Get(replacer, prop).
          3. Let item be undefined.
          4. If v is a String, then
            1. Set item to v.
          5. Else if v is a Number, then
            1. Set item to ! ToString(v).
          6. Else if v is an Object, then
            1. If v has a [[StringData]] or [[NumberData]] internal slot, set item to ? ToString(v).
          7. If item is not undefined and PropertyList does not contain item, then
            1. Append item to PropertyList.
          8. Set k to k + 1.
  6. If space is an Object, then
    1. If space has a [[NumberData]] internal slot, then
      1. Set space to ? ToNumber(space).
    2. Else if space has a [[StringData]] internal slot, then
      1. Set space to ? ToString(space).
  7. If space is a Number, then
    1. Let spaceMV be ! ToIntegerOrInfinity(space).
    2. Set spaceMV to min(10, spaceMV).
    3. If spaceMV < 1, let gap be the empty String; otherwise let gap be the String value containing spaceMV occurrences of the code unit 0x0020 (SPACE).
  8. Else if space is a String, then
    1. If the length of space ≤ 10, let gap be space; otherwise let gap be the substring of space from 0 to 10.
  9. Else,
    1. Let gap be the empty String.
  10. Let wrapper be OrdinaryObjectCreate(%Object.prototype%).
  11. Perform ! CreateDataPropertyOrThrow(wrapper, the empty String, value).
  12. Let state be the JSON Serialization Record { [[ReplacerFunction]]: ReplacerFunction, [[Stack]]: stack, [[Indent]]: indent, [[Gap]]: gap, [[PropertyList]]: PropertyList }.
  13. Return ? SerializeJSONProperty(state, the empty String, wrapper).

The "length" property of this function is 3𝔽.

Note 1

JSON structures are allowed to be nested to any depth, but they must be acyclic. If value is or contains a cyclic structure, then this function must throw a TypeError exception. This is an example of a value that cannot be stringified:

a = [];
a[0] = a;
my_text = JSON.stringify(a); // This must throw a TypeError.
Note 2

Symbolic primitive values are rendered as follows:

  • The null value is rendered in JSON text as the String value "null".
  • The undefined value is not rendered.
  • The true value is rendered in JSON text as the String value "true".
  • The false value is rendered in JSON text as the String value "false".
Note 3

String values are wrapped in QUOTATION MARK (") code units. The code units " and \ are escaped with \ prefixes. Control characters code units are replaced with escape sequences \uHHHH, or with the shorter forms, \b (BACKSPACE), \f (FORM FEED), \n (LINE FEED), \r (CARRIAGE RETURN), \t (CHARACTER TABULATION).

Note 4

Finite numbers are stringified as if by calling ToString(number). NaN and Infinity regardless of sign are represented as the String value "null".

Note 5

Values that do not have a JSON representation (such as undefined and functions) do not produce a String. Instead they produce the undefined value. In arrays these values are represented as the String value "null". In objects an unrepresentable value causes the property to be excluded from stringification.

Note 6

An object is rendered as U+007B (LEFT CURLY BRACKET) followed by zero or more properties, separated with a U+002C (COMMA), closed with a U+007D (RIGHT CURLY BRACKET). A property is a quoted String representing the property name, a U+003A (COLON), and then the stringified property value. An array is rendered as an opening U+005B (LEFT SQUARE BRACKET) followed by zero or more values, separated with a U+002C (COMMA), closed with a U+005D (RIGHT SQUARE BRACKET).

25.5.2.1 JSON Serialization Record

A JSON Serialization Record is a Record value used to enable serialization to the JSON format.

JSON Serialization Records have the fields listed in Table 80.

Table 80: JSON Serialization Record Fields
Field Name Value Meaning
[[ReplacerFunction]] a function object or undefined A function that can supply replacement values for object properties (from JSON.stringify's replacer parameter).
[[PropertyList]] either a List of Strings or undefined The names of properties to include when serializing a non-array object (from JSON.stringify's replacer parameter).
[[Gap]] a String The unit of indentation (from JSON.stringify's space parameter).
[[Stack]] a List of Objects The set of nested objects that are in the process of being serialized. Used to detect cyclic structures.
[[Indent]] a String The current indentation.

25.5.2.2 SerializeJSONProperty ( state, key, holder )

The abstract operation SerializeJSONProperty takes arguments state (a JSON Serialization Record), key (a String), and holder (an Object) and returns either a normal completion containing either a String or undefined, or a throw completion. It performs the following steps when called:

  1. Let value be ? Get(holder, key).
  2. If value is an Object or value is a BigInt, then
    1. Let toJSON be ? GetV(value, "toJSON").
    2. If IsCallable(toJSON) is true, then
      1. Set value to ? Call(toJSON, value, « key »).
  3. If state.[[ReplacerFunction]] is not undefined, then
    1. Set value to ? Call(state.[[ReplacerFunction]], holder, « key, value »).
  4. If value is an Object, then
    1. If value has a [[NumberData]] internal slot, then
      1. Set value to ? ToNumber(value).
    2. Else if value has a [[StringData]] internal slot, then
      1. Set value to ? ToString(value).
    3. Else if value has a [[BooleanData]] internal slot, then
      1. Set value to value.[[BooleanData]].
    4. Else if value has a [[BigIntData]] internal slot, then
      1. Set value to value.[[BigIntData]].
  5. If value is null, return "null".
  6. If value is true, return "true".
  7. If value is false, return "false".
  8. If value is a String, return QuoteJSONString(value).
  9. If value is a Number, then
    1. If value is finite, return ! ToString(value).
    2. Return "null".
  10. If value is a BigInt, throw a TypeError exception.
  11. If value is an Object and IsCallable(value) is false, then
    1. Let isArray be ? IsArray(value).
    2. If isArray is true, return ? SerializeJSONArray(state, value).
    3. Return ? SerializeJSONObject(state, value).
  12. Return undefined.

25.5.2.3 QuoteJSONString ( value )

The abstract operation QuoteJSONString takes argument value (a String) and returns a String. It wraps value in 0x0022 (QUOTATION MARK) code units and escapes certain other code units within it. This operation interprets value as a sequence of UTF-16 encoded code points, as described in 6.1.4. It performs the following steps when called:

  1. Let product be the String value consisting solely of the code unit 0x0022 (QUOTATION MARK).
  2. For each code point C of StringToCodePoints(value), do
    1. If C is listed in the “Code Point” column of Table 81, then
      1. Set product to the string-concatenation of product and the escape sequence for C as specified in the “Escape Sequence” column of the corresponding row.
    2. Else if C has a numeric value less than 0x0020 (SPACE) or C has the same numeric value as a leading surrogate or trailing surrogate, then
      1. Let unit be the code unit whose numeric value is the numeric value of C.
      2. Set product to the string-concatenation of product and UnicodeEscape(unit).
    3. Else,
      1. Set product to the string-concatenation of product and UTF16EncodeCodePoint(C).
  3. Set product to the string-concatenation of product and the code unit 0x0022 (QUOTATION MARK).
  4. Return product.
Table 81: JSON Single Character Escape Sequences
Code Point Unicode Character Name Escape Sequence
U+0008 BACKSPACE \b
U+0009 CHARACTER TABULATION \t
U+000A LINE FEED (LF) \n
U+000C FORM FEED (FF) \f
U+000D CARRIAGE RETURN (CR) \r
U+0022 QUOTATION MARK \"
U+005C REVERSE SOLIDUS \\

25.5.2.4 UnicodeEscape ( C )

The abstract operation UnicodeEscape takes argument C (a code unit) and returns a String. It represents C as a Unicode escape sequence. It performs the following steps when called:

  1. Let n be the numeric value of C.
  2. Assert: n ≤ 0xFFFF.
  3. Let hex be the String representation of n, formatted as a lowercase hexadecimal number.
  4. Return the string-concatenation of the code unit 0x005C (REVERSE SOLIDUS), "u", and StringPad(hex, 4, "0", start).

25.5.2.5 SerializeJSONObject ( state, value )

The abstract operation SerializeJSONObject takes arguments state (a JSON Serialization Record) and value (an Object) and returns either a normal completion containing a String or a throw completion. It serializes an object. It performs the following steps when called:

  1. If state.[[Stack]] contains value, throw a TypeError exception because the structure is cyclical.
  2. Append value to state.[[Stack]].
  3. Let stepBack be state.[[Indent]].
  4. Set state.[[Indent]] to the string-concatenation of state.[[Indent]] and state.[[Gap]].
  5. If state.[[PropertyList]] is not undefined, then
    1. Let K be state.[[PropertyList]].
  6. Else,
    1. Let K be ? EnumerableOwnProperties(value, key).
  7. Let partial be a new empty List.
  8. For each element P of K, do
    1. Let strP be ? SerializeJSONProperty(state, P, value).
    2. If strP is not undefined, then
      1. Let member be QuoteJSONString(P).
      2. Set member to the string-concatenation of member and ":".
      3. If state.[[Gap]] is not the empty String, then
        1. Set member to the string-concatenation of member and the code unit 0x0020 (SPACE).
      4. Set member to the string-concatenation of member and strP.
      5. Append member to partial.
  9. If partial is empty, then
    1. Let final be "{}".
  10. Else,
    1. If state.[[Gap]] is the empty String, then
      1. Let properties be the String value formed by concatenating all the element Strings of partial with each adjacent pair of Strings separated with the code unit 0x002C (COMMA). A comma is not inserted either before the first String or after the last String.
      2. Let final be the string-concatenation of "{", properties, and "}".
    2. Else,
      1. Let separator be the string-concatenation of the code unit 0x002C (COMMA), the code unit 0x000A (LINE FEED), and state.[[Indent]].
      2. Let properties be the String value formed by concatenating all the element Strings of partial with each adjacent pair of Strings separated with separator. The separator String is not inserted either before the first String or after the last String.
      3. Let final be the string-concatenation of "{", the code unit 0x000A (LINE FEED), state.[[Indent]], properties, the code unit 0x000A (LINE FEED), stepBack, and "}".
  11. Remove the last element of state.[[Stack]].
  12. Set state.[[Indent]] to stepBack.
  13. Return final.

25.5.2.6 SerializeJSONArray ( state, value )

The abstract operation SerializeJSONArray takes arguments state (a JSON Serialization Record) and value (an ECMAScript language value) and returns either a normal completion containing a String or a throw completion. It serializes an array. It performs the following steps when called:

  1. If state.[[Stack]] contains value, throw a TypeError exception because the structure is cyclical.
  2. Append value to state.[[Stack]].
  3. Let stepBack be state.[[Indent]].
  4. Set state.[[Indent]] to the string-concatenation of state.[[Indent]] and state.[[Gap]].
  5. Let partial be a new empty List.
  6. Let len be ? LengthOfArrayLike(value).
  7. Let index be 0.
  8. Repeat, while index < len,
    1. Let strP be ? SerializeJSONProperty(state, ! ToString(𝔽(index)), value).
    2. If strP is undefined, then
      1. Append "null" to partial.
    3. Else,
      1. Append strP to partial.
    4. Set index to index + 1.
  9. If partial is empty, then
    1. Let final be "[]".
  10. Else,
    1. If state.[[Gap]] is the empty String, then
      1. Let properties be the String value formed by concatenating all the element Strings of partial with each adjacent pair of Strings separated with the code unit 0x002C (COMMA). A comma is not inserted either before the first String or after the last String.
      2. Let final be the string-concatenation of "[", properties, and "]".
    2. Else,
      1. Let separator be the string-concatenation of the code unit 0x002C (COMMA), the code unit 0x000A (LINE FEED), and state.[[Indent]].
      2. Let properties be the String value formed by concatenating all the element Strings of partial with each adjacent pair of Strings separated with separator. The separator String is not inserted either before the first String or after the last String.
      3. Let final be the string-concatenation of "[", the code unit 0x000A (LINE FEED), state.[[Indent]], properties, the code unit 0x000A (LINE FEED), stepBack, and "]".
  11. Remove the last element of state.[[Stack]].
  12. Set state.[[Indent]] to stepBack.
  13. Return final.
Note

The representation of arrays includes only the elements in the interval from +0𝔽 (inclusive) to array.length (exclusive). Properties whose keys are not array indices are excluded from the stringification. An array is stringified as an opening LEFT SQUARE BRACKET, elements separated by COMMA, and a closing RIGHT SQUARE BRACKET.

25.5.3 JSON [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "JSON".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

26 Managing Memory

26.1 WeakRef Objects

A WeakRef is an object that is used to refer to a target object or symbol without preserving it from garbage collection. WeakRefs can be dereferenced to allow access to the target value, if the target hasn't been reclaimed by garbage collection.

26.1.1 The WeakRef Constructor

The WeakRef constructor:

  • is %WeakRef%.
  • is the initial value of the "WeakRef" property of the global object.
  • creates and initializes a new WeakRef when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified WeakRef behaviour must include a super call to the WeakRef constructor to create and initialize the subclass instance with the internal state necessary to support the WeakRef.prototype built-in methods.

26.1.1.1 WeakRef ( target )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If CanBeHeldWeakly(target) is false, throw a TypeError exception.
  3. Let weakRef be ? OrdinaryCreateFromConstructor(NewTarget, "%WeakRef.prototype%", « [[WeakRefTarget]] »).
  4. Perform AddToKeptObjects(target).
  5. Set weakRef.[[WeakRefTarget]] to target.
  6. Return weakRef.

26.1.2 Properties of the WeakRef Constructor

The WeakRef constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

26.1.2.1 WeakRef.prototype

The initial value of WeakRef.prototype is the WeakRef prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

26.1.3 Properties of the WeakRef Prototype Object

The WeakRef prototype object:

  • is %WeakRef.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have a [[WeakRefTarget]] internal slot.

26.1.3.1 WeakRef.prototype.constructor

The initial value of WeakRef.prototype.constructor is %WeakRef%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

26.1.3.2 WeakRef.prototype.deref ( )

This method performs the following steps when called:

  1. Let weakRef be the this value.
  2. Perform ? RequireInternalSlot(weakRef, [[WeakRefTarget]]).
  3. Return WeakRefDeref(weakRef).
Note

If the WeakRef returns a target value that is not undefined, then this target value should not be garbage collected until the current execution of ECMAScript code has completed. The AddToKeptObjects operation makes sure read consistency is maintained.

let target = { foo() {} };
let weakRef = new WeakRef(target);

// ... later ...

if (weakRef.deref()) {
  weakRef.deref().foo();
}

In the above example, if the first deref does not evaluate to undefined then the second deref cannot either.

26.1.3.3 WeakRef.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "WeakRef".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

26.1.4 WeakRef Abstract Operations

26.1.4.1 WeakRefDeref ( weakRef )

The abstract operation WeakRefDeref takes argument weakRef (a WeakRef) and returns an ECMAScript language value. It performs the following steps when called:

  1. Let target be weakRef.[[WeakRefTarget]].
  2. If target is not empty, then
    1. Perform AddToKeptObjects(target).
    2. Return target.
  3. Return undefined.
Note

This abstract operation is defined separately from WeakRef.prototype.deref strictly to make it possible to succinctly define liveness.

26.1.5 Properties of WeakRef Instances

WeakRef instances are ordinary objects that inherit properties from the WeakRef prototype. WeakRef instances also have a [[WeakRefTarget]] internal slot.

26.2 FinalizationRegistry Objects

A FinalizationRegistry is an object that manages registration and unregistration of cleanup operations that are performed when target objects and symbols are garbage collected.

26.2.1 The FinalizationRegistry Constructor

The FinalizationRegistry constructor:

  • is %FinalizationRegistry%.
  • is the initial value of the "FinalizationRegistry" property of the global object.
  • creates and initializes a new FinalizationRegistry when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified FinalizationRegistry behaviour must include a super call to the FinalizationRegistry constructor to create and initialize the subclass instance with the internal state necessary to support the FinalizationRegistry.prototype built-in methods.

26.2.1.1 FinalizationRegistry ( cleanupCallback )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If IsCallable(cleanupCallback) is false, throw a TypeError exception.
  3. Let finalizationRegistry be ? OrdinaryCreateFromConstructor(NewTarget, "%FinalizationRegistry.prototype%", « [[Realm]], [[CleanupCallback]], [[Cells]] »).
  4. Let fn be the active function object.
  5. Set finalizationRegistry.[[Realm]] to fn.[[Realm]].
  6. Set finalizationRegistry.[[CleanupCallback]] to HostMakeJobCallback(cleanupCallback).
  7. Set finalizationRegistry.[[Cells]] to a new empty List.
  8. Return finalizationRegistry.

26.2.2 Properties of the FinalizationRegistry Constructor

The FinalizationRegistry constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

26.2.2.1 FinalizationRegistry.prototype

The initial value of FinalizationRegistry.prototype is the FinalizationRegistry prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

26.2.3 Properties of the FinalizationRegistry Prototype Object

The FinalizationRegistry prototype object:

  • is %FinalizationRegistry.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have [[Cells]] and [[CleanupCallback]] internal slots.

26.2.3.1 FinalizationRegistry.prototype.constructor

The initial value of FinalizationRegistry.prototype.constructor is %FinalizationRegistry%.

26.2.3.2 FinalizationRegistry.prototype.register ( target, heldValue [ , unregisterToken ] )

This method performs the following steps when called:

  1. Let finalizationRegistry be the this value.
  2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
  3. If CanBeHeldWeakly(target) is false, throw a TypeError exception.
  4. If SameValue(target, heldValue) is true, throw a TypeError exception.
  5. If CanBeHeldWeakly(unregisterToken) is false, then
    1. If unregisterToken is not undefined, throw a TypeError exception.
    2. Set unregisterToken to empty.
  6. Let cell be the Record { [[WeakRefTarget]]: target, [[HeldValue]]: heldValue, [[UnregisterToken]]: unregisterToken }.
  7. Append cell to finalizationRegistry.[[Cells]].
  8. Return undefined.
Note

Based on the algorithms and definitions in this specification, cell.[[HeldValue]] is live when finalizationRegistry.[[Cells]] contains cell; however, this does not necessarily mean that cell.[[UnregisterToken]] or cell.[[Target]] are live. For example, registering an object with itself as its unregister token would not keep the object alive forever.

26.2.3.3 FinalizationRegistry.prototype.unregister ( unregisterToken )

This method performs the following steps when called:

  1. Let finalizationRegistry be the this value.
  2. Perform ? RequireInternalSlot(finalizationRegistry, [[Cells]]).
  3. If CanBeHeldWeakly(unregisterToken) is false, throw a TypeError exception.
  4. Let removed be false.
  5. For each Record { [[WeakRefTarget]], [[HeldValue]], [[UnregisterToken]] } cell of finalizationRegistry.[[Cells]], do
    1. If cell.[[UnregisterToken]] is not empty and SameValue(cell.[[UnregisterToken]], unregisterToken) is true, then
      1. Remove cell from finalizationRegistry.[[Cells]].
      2. Set removed to true.
  6. Return removed.

26.2.3.4 FinalizationRegistry.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "FinalizationRegistry".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

26.2.4 Properties of FinalizationRegistry Instances

FinalizationRegistry instances are ordinary objects that inherit properties from the FinalizationRegistry prototype. FinalizationRegistry instances also have [[Cells]] and [[CleanupCallback]] internal slots.

27 Control Abstraction Objects

27.1 Iteration

27.1.1 Common Iteration Interfaces

An interface is a set of property keys whose associated values match a specific specification. Any object that provides all the properties as described by an interface's specification conforms to that interface. An interface is not represented by a distinct object. There may be many separately implemented objects that conform to any interface. An individual object may conform to multiple interfaces.

27.1.1.1 The Iterable Interface

The iterable interface includes the property described in Table 82:

Table 82: Iterable Interface Required Properties
Property Value Requirements
%Symbol.iterator% a function that returns an iterator object The returned object must conform to the iterator interface.

27.1.1.2 The Iterator Interface

An object that implements the iterator interface must include the property in Table 83. Such objects may also implement the properties in Table 84.

Table 83: Iterator Interface Required Properties
Property Value Requirements
"next" a function that returns an IteratorResult object The returned object must conform to the IteratorResult interface. If a previous call to the next method of an iterator has returned an IteratorResult object whose "done" property is true, then all subsequent calls to the next method of that object should also return an IteratorResult object whose "done" property is true. However, this requirement is not enforced.
Note 1

Arguments may be passed to the next function but their interpretation and validity is dependent upon the target iterator. The for-of statement and other common users of iterators do not pass any arguments, so iterator objects that expect to be used in such a manner must be prepared to deal with being called with no arguments.

Table 84: Iterator Interface Optional Properties
Property Value Requirements
"return" a function that returns an IteratorResult object The returned object must conform to the IteratorResult interface. Invoking this method notifies the iterator object that the caller does not intend to make any more next method calls to the iterator. The returned IteratorResult object will typically have a "done" property whose value is true, and a "value" property with the value passed as the argument of the return method. However, this requirement is not enforced.
"throw" a function that returns an IteratorResult object The returned object must conform to the IteratorResult interface. Invoking this method notifies the iterator object that the caller has detected an error condition. The argument may be used to identify the error condition and typically will be an exception object. A typical response is to throw the value passed as the argument. If the method does not throw, the returned IteratorResult object will typically have a "done" property whose value is true.
Note 2

Typically callers of these methods should check for their existence before invoking them. Certain ECMAScript language features including for-of, yield*, and array destructuring call these methods after performing an existence check. Most ECMAScript library functions that accept iterable objects as arguments also conditionally call them.

27.1.1.3 The Async Iterable Interface

The async iterable interface includes the properties described in Table 85:

Table 85: Async Iterable Interface Required Properties
Property Value Requirements
%Symbol.asyncIterator% a function that returns an async iterator object The returned object must conform to the async iterator interface.

27.1.1.4 The Async Iterator Interface

An object that implements the async iterator interface must include the properties in Table 86. Such objects may also implement the properties in Table 87.

Table 86: Async Iterator Interface Required Properties
Property Value Requirements
"next" a function that returns a promise for an IteratorResult object

The returned promise, when fulfilled, must fulfill with an object that conforms to the IteratorResult interface. If a previous call to the next method of an async iterator has returned a promise for an IteratorResult object whose "done" property is true, then all subsequent calls to the next method of that object should also return a promise for an IteratorResult object whose "done" property is true. However, this requirement is not enforced.

Additionally, the IteratorResult object that serves as a fulfillment value should have a "value" property whose value is not a promise (or "thenable"). However, this requirement is also not enforced.

Note 1

Arguments may be passed to the next function but their interpretation and validity is dependent upon the target async iterator. The for-await-of statement and other common users of async iterators do not pass any arguments, so async iterator objects that expect to be used in such a manner must be prepared to deal with being called with no arguments.

Table 87: Async Iterator Interface Optional Properties
Property Value Requirements
"return" a function that returns a promise for an IteratorResult object

The returned promise, when fulfilled, must fulfill with an object that conforms to the IteratorResult interface. Invoking this method notifies the async iterator object that the caller does not intend to make any more next method calls to the async iterator. The returned promise will fulfill with an IteratorResult object which will typically have a "done" property whose value is true, and a "value" property with the value passed as the argument of the return method. However, this requirement is not enforced.

Additionally, the IteratorResult object that serves as a fulfillment value should have a "value" property whose value is not a promise (or "thenable"). If the argument value is used in the typical manner, then if it is a rejected promise, a promise rejected with the same reason should be returned; if it is a fulfilled promise, then its fulfillment value should be used as the "value" property of the returned promise's IteratorResult object fulfillment value. However, these requirements are also not enforced.

"throw" a function that returns a promise for an IteratorResult object

The returned promise, when fulfilled, must fulfill with an object that conforms to the IteratorResult interface. Invoking this method notifies the async iterator object that the caller has detected an error condition. The argument may be used to identify the error condition and typically will be an exception object. A typical response is to return a rejected promise which rejects with the value passed as the argument.

If the returned promise is fulfilled, the IteratorResult object fulfillment value will typically have a "done" property whose value is true. Additionally, it should have a "value" property whose value is not a promise (or "thenable"), but this requirement is not enforced.

Note 2

Typically callers of these methods should check for their existence before invoking them. Certain ECMAScript language features including for-await-of and yield* call these methods after performing an existence check.

27.1.1.5 The IteratorResult Interface

The IteratorResult interface includes the properties listed in Table 88:

Table 88: IteratorResult Interface Properties
Property Value Requirements
"done" a Boolean This is the result status of an iterator next method call. If the end of the iterator was reached "done" is true. If the end was not reached "done" is false and a value is available. If a "done" property (either own or inherited) does not exist, it is considered to have the value false.
"value" an ECMAScript language value If done is false, this is the current iteration element value. If done is true, this is the return value of the iterator, if it supplied one. If the iterator does not have a return value, "value" is undefined. In that case, the "value" property may be absent from the conforming object if it does not inherit an explicit "value" property.

27.1.2 Iterator Helper Objects

An Iterator Helper object is an ordinary object that represents a lazy transformation of some specific source iterator object. There is not a named constructor for Iterator Helper objects. Instead, Iterator Helper objects are created by calling certain methods of Iterator instance objects.

27.1.2.1 The %IteratorHelperPrototype% Object

The %IteratorHelperPrototype% object:

27.1.2.1.1 %IteratorHelperPrototype%.next ( )

  1. Return ? GeneratorResume(this value, undefined, "Iterator Helper").

27.1.2.1.2 %IteratorHelperPrototype%.return ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[UnderlyingIterator]]).
  3. Assert: O has a [[GeneratorState]] internal slot.
  4. If O.[[GeneratorState]] is suspended-start, then
    1. Set O.[[GeneratorState]] to completed.
    2. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with O can be discarded at this point.
    3. Perform ? IteratorClose(O.[[UnderlyingIterator]], NormalCompletion(unused)).
    4. Return CreateIteratorResultObject(undefined, true).
  5. Let C be ReturnCompletion(undefined).
  6. Return ? GeneratorResumeAbrupt(O, C, "Iterator Helper").

27.1.2.1.3 %IteratorHelperPrototype% [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "Iterator Helper".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.1.3 Iterator Objects

27.1.3.1 The Iterator Constructor

The Iterator constructor:

  • is %Iterator%.
  • is the initial value of the "Iterator" property of the global object.
  • is designed to be subclassable. It may be used as the value of an extends clause of a class definition.

27.1.3.1.1 Iterator ( )

This function performs the following steps when called:

  1. If NewTarget is either undefined or the active function object, throw a TypeError exception.
  2. Return ? OrdinaryCreateFromConstructor(NewTarget, "%Iterator.prototype%").

27.1.3.2 Properties of the Iterator Constructor

The Iterator constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

27.1.3.2.1 Iterator.from ( O )

  1. Let iteratorRecord be ? GetIteratorFlattenable(O, iterate-string-primitives).
  2. Let hasInstance be ? OrdinaryHasInstance(%Iterator%, iteratorRecord.[[Iterator]]).
  3. If hasInstance is true, then
    1. Return iteratorRecord.[[Iterator]].
  4. Let wrapper be OrdinaryObjectCreate(%WrapForValidIteratorPrototype%, « [[Iterated]] »).
  5. Set wrapper.[[Iterated]] to iteratorRecord.
  6. Return wrapper.

27.1.3.2.1.1 The %WrapForValidIteratorPrototype% Object

The %WrapForValidIteratorPrototype% object:

27.1.3.2.1.1.1 %WrapForValidIteratorPrototype%.next ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[Iterated]]).
  3. Let iteratorRecord be O.[[Iterated]].
  4. Return ? Call(iteratorRecord.[[NextMethod]], iteratorRecord.[[Iterator]]).

27.1.3.2.1.1.2 %WrapForValidIteratorPrototype%.return ( )

  1. Let O be this value.
  2. Perform ? RequireInternalSlot(O, [[Iterated]]).
  3. Let iterator be O.[[Iterated]].[[Iterator]].
  4. Assert: iterator is an Object.
  5. Let returnMethod be ? GetMethod(iterator, "return").
  6. If returnMethod is undefined, then
    1. Return CreateIteratorResultObject(undefined, true).
  7. Return ? Call(returnMethod, iterator).

27.1.3.2.2 Iterator.prototype

The initial value of Iterator.prototype is the Iterator prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.1.4 Properties of the Iterator Prototype Object

The Iterator prototype object:

Note

All objects defined in this specification that implement the iterator interface also inherit from %Iterator.prototype%. ECMAScript code may also define objects that inherit from %Iterator.prototype%. %Iterator.prototype% provides a place where additional methods that are applicable to all iterator objects may be added.

The following expression is one way that ECMAScript code can access the %Iterator.prototype% object:

Object.getPrototypeOf(Object.getPrototypeOf([][Symbol.iterator]()))

27.1.4.1 Iterator.prototype.constructor

Iterator.prototype.constructor is an accessor property with attributes { [[Enumerable]]: false, [[Configurable]]: true }. The [[Get]] and [[Set]] attributes are defined as follows:

27.1.4.1.1 get Iterator.prototype.constructor

The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

  1. Return %Iterator%.

27.1.4.1.2 set Iterator.prototype.constructor

The value of the [[Set]] attribute is a built-in function that takes an argument v. It performs the following steps when called:

  1. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, "constructor", v).
  2. Return undefined.
Note

Unlike the "constructor" property on most built-in prototypes, for web-compatibility reasons this property must be an accessor.

27.1.4.2 Iterator.prototype.drop ( limit )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. Let numLimit be Completion(ToNumber(limit)).
  5. IfAbruptCloseIterator(numLimit, iterated).
  6. If numLimit is NaN, then
    1. Let error be ThrowCompletion(a newly created RangeError object).
    2. Return ? IteratorClose(iterated, error).
  7. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  8. If integerLimit < 0, then
    1. Let error be ThrowCompletion(a newly created RangeError object).
    2. Return ? IteratorClose(iterated, error).
  9. Set iterated to ? GetIteratorDirect(O).
  10. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat, while remaining > 0,
      1. If remaining ≠ +∞, then
        1. Set remaining to remaining - 1.
      2. Let next be ? IteratorStep(iterated).
      3. If next is done, return ReturnCompletion(undefined).
    3. Repeat,
      1. Let value be ? IteratorStepValue(iterated).
      2. If value is done, return ReturnCompletion(undefined).
      3. Let completion be Completion(Yield(value)).
      4. IfAbruptCloseIterator(completion, iterated).
  11. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
  12. Set result.[[UnderlyingIterator]] to iterated.
  13. Return result.

27.1.4.3 Iterator.prototype.every ( predicate )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(predicate) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let counter be 0.
  7. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return true.
    3. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
    4. IfAbruptCloseIterator(result, iterated).
    5. If ToBoolean(result) is false, return ? IteratorClose(iterated, NormalCompletion(false)).
    6. Set counter to counter + 1.

27.1.4.4 Iterator.prototype.filter ( predicate )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(predicate) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and predicate and performs the following steps when called:
    1. Let counter be 0.
    2. Repeat,
      1. Let value be ? IteratorStepValue(iterated).
      2. If value is done, return ReturnCompletion(undefined).
      3. Let selected be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
      4. IfAbruptCloseIterator(selected, iterated).
      5. If ToBoolean(selected) is true, then
        1. Let completion be Completion(Yield(value)).
        2. IfAbruptCloseIterator(completion, iterated).
      6. Set counter to counter + 1.
  7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
  8. Set result.[[UnderlyingIterator]] to iterated.
  9. Return result.

27.1.4.5 Iterator.prototype.find ( predicate )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(predicate) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let counter be 0.
  7. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return undefined.
    3. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
    4. IfAbruptCloseIterator(result, iterated).
    5. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(value)).
    6. Set counter to counter + 1.

27.1.4.6 Iterator.prototype.flatMap ( mapper )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(mapper) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Let counter be 0.
    2. Repeat,
      1. Let value be ? IteratorStepValue(iterated).
      2. If value is done, return ReturnCompletion(undefined).
      3. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
      4. IfAbruptCloseIterator(mapped, iterated).
      5. Let innerIterator be Completion(GetIteratorFlattenable(mapped, reject-primitives)).
      6. IfAbruptCloseIterator(innerIterator, iterated).
      7. Let innerAlive be true.
      8. Repeat, while innerAlive is true,
        1. Let innerValue be Completion(IteratorStepValue(innerIterator)).
        2. IfAbruptCloseIterator(innerValue, iterated).
        3. If innerValue is done, then
          1. Set innerAlive to false.
        4. Else,
          1. Let completion be Completion(Yield(innerValue)).
          2. If completion is an abrupt completion, then
            1. Let backupCompletion be Completion(IteratorClose(innerIterator, completion)).
            2. IfAbruptCloseIterator(backupCompletion, iterated).
            3. Return ? IteratorClose(iterated, completion).
      9. Set counter to counter + 1.
  7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
  8. Set result.[[UnderlyingIterator]] to iterated.
  9. Return result.

27.1.4.7 Iterator.prototype.forEach ( procedure )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(procedure) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let counter be 0.
  7. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return undefined.
    3. Let result be Completion(Call(procedure, undefined, « value, 𝔽(counter) »)).
    4. IfAbruptCloseIterator(result, iterated).
    5. Set counter to counter + 1.

27.1.4.8 Iterator.prototype.map ( mapper )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(mapper) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let closure be a new Abstract Closure with no parameters that captures iterated and mapper and performs the following steps when called:
    1. Let counter be 0.
    2. Repeat,
      1. Let value be ? IteratorStepValue(iterated).
      2. If value is done, return ReturnCompletion(undefined).
      3. Let mapped be Completion(Call(mapper, undefined, « value, 𝔽(counter) »)).
      4. IfAbruptCloseIterator(mapped, iterated).
      5. Let completion be Completion(Yield(mapped)).
      6. IfAbruptCloseIterator(completion, iterated).
      7. Set counter to counter + 1.
  7. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
  8. Set result.[[UnderlyingIterator]] to iterated.
  9. Return result.

27.1.4.9 Iterator.prototype.reduce ( reducer [ , initialValue ] )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(reducer) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. If initialValue is not present, then
    1. Let accumulator be ? IteratorStepValue(iterated).
    2. If accumulator is done, throw a TypeError exception.
    3. Let counter be 1.
  7. Else,
    1. Let accumulator be initialValue.
    2. Let counter be 0.
  8. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return accumulator.
    3. Let result be Completion(Call(reducer, undefined, « accumulator, value, 𝔽(counter) »)).
    4. IfAbruptCloseIterator(result, iterated).
    5. Set accumulator to result.
    6. Set counter to counter + 1.

27.1.4.10 Iterator.prototype.some ( predicate )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. If IsCallable(predicate) is false, then
    1. Let error be ThrowCompletion(a newly created TypeError object).
    2. Return ? IteratorClose(iterated, error).
  5. Set iterated to ? GetIteratorDirect(O).
  6. Let counter be 0.
  7. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return false.
    3. Let result be Completion(Call(predicate, undefined, « value, 𝔽(counter) »)).
    4. IfAbruptCloseIterator(result, iterated).
    5. If ToBoolean(result) is true, return ? IteratorClose(iterated, NormalCompletion(true)).
    6. Set counter to counter + 1.

27.1.4.11 Iterator.prototype.take ( limit )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be the Iterator Record { [[Iterator]]: O, [[NextMethod]]: undefined, [[Done]]: false }.
  4. Let numLimit be Completion(ToNumber(limit)).
  5. IfAbruptCloseIterator(numLimit, iterated).
  6. If numLimit is NaN, then
    1. Let error be ThrowCompletion(a newly created RangeError object).
    2. Return ? IteratorClose(iterated, error).
  7. Let integerLimit be ! ToIntegerOrInfinity(numLimit).
  8. If integerLimit < 0, then
    1. Let error be ThrowCompletion(a newly created RangeError object).
    2. Return ? IteratorClose(iterated, error).
  9. Set iterated to ? GetIteratorDirect(O).
  10. Let closure be a new Abstract Closure with no parameters that captures iterated and integerLimit and performs the following steps when called:
    1. Let remaining be integerLimit.
    2. Repeat,
      1. If remaining = 0, then
        1. Return ? IteratorClose(iterated, ReturnCompletion(undefined)).
      2. If remaining ≠ +∞, then
        1. Set remaining to remaining - 1.
      3. Let value be ? IteratorStepValue(iterated).
      4. If value is done, return ReturnCompletion(undefined).
      5. Let completion be Completion(Yield(value)).
      6. IfAbruptCloseIterator(completion, iterated).
  11. Let result be CreateIteratorFromClosure(closure, "Iterator Helper", %IteratorHelperPrototype%, « [[UnderlyingIterator]] »).
  12. Set result.[[UnderlyingIterator]] to iterated.
  13. Return result.

27.1.4.12 Iterator.prototype.toArray ( )

This method performs the following steps when called:

  1. Let O be the this value.
  2. If O is not an Object, throw a TypeError exception.
  3. Let iterated be ? GetIteratorDirect(O).
  4. Let items be a new empty List.
  5. Repeat,
    1. Let value be ? IteratorStepValue(iterated).
    2. If value is done, return CreateArrayFromList(items).
    3. Append value to items.

27.1.4.13 Iterator.prototype [ %Symbol.iterator% ] ( )

This function performs the following steps when called:

  1. Return the this value.

The value of the "name" property of this function is "[Symbol.iterator]".

27.1.4.14 Iterator.prototype [ %Symbol.toStringTag% ]

Iterator.prototype[%Symbol.toStringTag%] is an accessor property with attributes { [[Enumerable]]: false, [[Configurable]]: true }. The [[Get]] and [[Set]] attributes are defined as follows:

27.1.4.14.1 get Iterator.prototype [ %Symbol.toStringTag% ]

The value of the [[Get]] attribute is a built-in function that requires no arguments. It performs the following steps when called:

  1. Return "Iterator".

27.1.4.14.2 set Iterator.prototype [ %Symbol.toStringTag% ]

The value of the [[Set]] attribute is a built-in function that takes an argument v. It performs the following steps when called:

  1. Perform ? SetterThatIgnoresPrototypeProperties(this value, %Iterator.prototype%, %Symbol.toStringTag%, v).
  2. Return undefined.
Note

Unlike the %Symbol.toStringTag% property on most built-in prototypes, for web-compatibility reasons this property must be an accessor.

27.1.5 The %AsyncIteratorPrototype% Object

The %AsyncIteratorPrototype% object:

Note

All objects defined in this specification that implement the async iterator interface also inherit from %AsyncIteratorPrototype%. ECMAScript code may also define objects that inherit from %AsyncIteratorPrototype%. The %AsyncIteratorPrototype% object provides a place where additional methods that are applicable to all async iterator objects may be added.

27.1.5.1 %AsyncIteratorPrototype% [ %Symbol.asyncIterator% ] ( )

This function performs the following steps when called:

  1. Return the this value.

The value of the "name" property of this function is "[Symbol.asyncIterator]".

27.1.6 Async-from-Sync Iterator Objects

An Async-from-Sync Iterator object is an async iterator that adapts a specific synchronous iterator. Async-from-Sync Iterator objects are never directly accessible to ECMAScript code. There is not a named constructor for Async-from-Sync Iterator objects. Instead, Async-from-Sync Iterator objects are created by the CreateAsyncFromSyncIterator abstract operation as needed.

27.1.6.1 CreateAsyncFromSyncIterator ( syncIteratorRecord )

The abstract operation CreateAsyncFromSyncIterator takes argument syncIteratorRecord (an Iterator Record) and returns an Iterator Record. It is used to create an async Iterator Record from a synchronous Iterator Record. It performs the following steps when called:

  1. Let asyncIterator be OrdinaryObjectCreate(%AsyncFromSyncIteratorPrototype%, « [[SyncIteratorRecord]] »).
  2. Set asyncIterator.[[SyncIteratorRecord]] to syncIteratorRecord.
  3. Let nextMethod be ! Get(asyncIterator, "next").
  4. Let iteratorRecord be the Iterator Record { [[Iterator]]: asyncIterator, [[NextMethod]]: nextMethod, [[Done]]: false }.
  5. Return iteratorRecord.

27.1.6.2 The %AsyncFromSyncIteratorPrototype% Object

The %AsyncFromSyncIteratorPrototype% object:

27.1.6.2.1 %AsyncFromSyncIteratorPrototype%.next ( [ value ] )

  1. Let O be the this value.
  2. Assert: O is an Object that has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
  5. If value is present, then
    1. Let result be Completion(IteratorNext(syncIteratorRecord, value)).
  6. Else,
    1. Let result be Completion(IteratorNext(syncIteratorRecord)).
  7. IfAbruptRejectPromise(result, promiseCapability).
  8. Return AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true).

27.1.6.2.2 %AsyncFromSyncIteratorPrototype%.return ( [ value ] )

  1. Let O be the this value.
  2. Assert: O is an Object that has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
  5. Let syncIterator be syncIteratorRecord.[[Iterator]].
  6. Let return be Completion(GetMethod(syncIterator, "return")).
  7. IfAbruptRejectPromise(return, promiseCapability).
  8. If return is undefined, then
    1. Let iteratorResult be CreateIteratorResultObject(value, true).
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
    3. Return promiseCapability.[[Promise]].
  9. If value is present, then
    1. Let result be Completion(Call(return, syncIterator, « value »)).
  10. Else,
    1. Let result be Completion(Call(return, syncIterator)).
  11. IfAbruptRejectPromise(result, promiseCapability).
  12. If result is not an Object, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    2. Return promiseCapability.[[Promise]].
  13. Return AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, false).

27.1.6.2.3 %AsyncFromSyncIteratorPrototype%.throw ( [ value ] )

Note
In this specification, value is always provided, but is left optional for consistency with %AsyncFromSyncIteratorPrototype%.return ( [ value ] ).
  1. Let O be the this value.
  2. Assert: O is an Object that has a [[SyncIteratorRecord]] internal slot.
  3. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  4. Let syncIteratorRecord be O.[[SyncIteratorRecord]].
  5. Let syncIterator be syncIteratorRecord.[[Iterator]].
  6. Let throw be Completion(GetMethod(syncIterator, "throw")).
  7. IfAbruptRejectPromise(throw, promiseCapability).
  8. If throw is undefined, then
    1. NOTE: If syncIterator does not have a throw method, close it to give it a chance to clean up before we reject the capability.
    2. Let closeCompletion be NormalCompletion(empty).
    3. Let result be Completion(IteratorClose(syncIteratorRecord, closeCompletion)).
    4. IfAbruptRejectPromise(result, promiseCapability).
    5. NOTE: The next step throws a TypeError to indicate that there was a protocol violation: syncIterator does not have a throw method.
    6. NOTE: If closing syncIterator does not throw then the result of that operation is ignored, even if it yields a rejected promise.
    7. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    8. Return promiseCapability.[[Promise]].
  9. If value is present, then
    1. Let result be Completion(Call(throw, syncIterator, « value »)).
  10. Else,
    1. Let result be Completion(Call(throw, syncIterator)).
  11. IfAbruptRejectPromise(result, promiseCapability).
  12. If result is not an Object, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « a newly created TypeError object »).
    2. Return promiseCapability.[[Promise]].
  13. Return AsyncFromSyncIteratorContinuation(result, promiseCapability, syncIteratorRecord, true).

27.1.6.3 Properties of Async-from-Sync Iterator Instances

Async-from-Sync Iterator instances are ordinary objects that inherit properties from the %AsyncFromSyncIteratorPrototype% intrinsic object. Async-from-Sync Iterator instances are initially created with the internal slots listed in Table 89.

Table 89: Internal Slots of Async-from-Sync Iterator Instances
Internal Slot Type Description
[[SyncIteratorRecord]] an Iterator Record Represents the original synchronous iterator which is being adapted.

27.1.6.4 AsyncFromSyncIteratorContinuation ( result, promiseCapability, syncIteratorRecord, closeOnRejection )

The abstract operation AsyncFromSyncIteratorContinuation takes arguments result (an Object), promiseCapability (a PromiseCapability Record for an intrinsic %Promise%), syncIteratorRecord (an Iterator Record), and closeOnRejection (a Boolean) and returns a Promise. It performs the following steps when called:

  1. NOTE: Because promiseCapability is derived from the intrinsic %Promise%, the calls to promiseCapability.[[Reject]] entailed by the use IfAbruptRejectPromise below are guaranteed not to throw.
  2. Let done be Completion(IteratorComplete(result)).
  3. IfAbruptRejectPromise(done, promiseCapability).
  4. Let value be Completion(IteratorValue(result)).
  5. IfAbruptRejectPromise(value, promiseCapability).
  6. Let valueWrapper be Completion(PromiseResolve(%Promise%, value)).
  7. If valueWrapper is an abrupt completion, done is false, and closeOnRejection is true, then
    1. Set valueWrapper to Completion(IteratorClose(syncIteratorRecord, valueWrapper)).
  8. IfAbruptRejectPromise(valueWrapper, promiseCapability).
  9. Let unwrap be a new Abstract Closure with parameters (v) that captures done and performs the following steps when called:
    1. Return CreateIteratorResultObject(v, done).
  10. Let onFulfilled be CreateBuiltinFunction(unwrap, 1, "", « »).
  11. NOTE: onFulfilled is used when processing the "value" property of an IteratorResult object in order to wait for its value if it is a promise and re-package the result in a new "unwrapped" IteratorResult object.
  12. If done is true, or if closeOnRejection is false, then
    1. Let onRejected be undefined.
  13. Else,
    1. Let closeIterator be a new Abstract Closure with parameters (error) that captures syncIteratorRecord and performs the following steps when called:
      1. Return ? IteratorClose(syncIteratorRecord, ThrowCompletion(error)).
    2. Let onRejected be CreateBuiltinFunction(closeIterator, 1, "", « »).
    3. NOTE: onRejected is used to close the Iterator when the "value" property of an IteratorResult object it yields is a rejected promise.
  14. Perform PerformPromiseThen(valueWrapper, onFulfilled, onRejected, promiseCapability).
  15. Return promiseCapability.[[Promise]].

27.2 Promise Objects

A Promise is an object that is used as a placeholder for the eventual results of a deferred (and possibly asynchronous) computation.

Any Promise is in one of three mutually exclusive states: fulfilled, rejected, and pending:

  • A promise p is fulfilled if p.then(f, r) will immediately enqueue a Job to call the function f.
  • A promise p is rejected if p.then(f, r) will immediately enqueue a Job to call the function r.
  • A promise is pending if it is neither fulfilled nor rejected.

A promise is said to be settled if it is not pending, i.e. if it is either fulfilled or rejected.

A promise is resolved if it is settled or if it has been “locked in” to match the state of another promise. Attempting to resolve or reject a resolved promise has no effect. A promise is unresolved if it is not resolved. An unresolved promise is always in the pending state. A resolved promise may be pending, fulfilled or rejected.

27.2.1 Promise Abstract Operations

27.2.1.1 PromiseCapability Records

A PromiseCapability Record is a Record value used to encapsulate a Promise or promise-like object along with the functions that are capable of resolving or rejecting that promise. PromiseCapability Records are produced by the NewPromiseCapability abstract operation.

PromiseCapability Records have the fields listed in Table 90.

Table 90: PromiseCapability Record Fields
Field Name Value Meaning
[[Promise]] an Object An object that is usable as a promise.
[[Resolve]] a function object The function that is used to resolve the given promise.
[[Reject]] a function object The function that is used to reject the given promise.

27.2.1.1.1 IfAbruptRejectPromise ( value, capability )

IfAbruptRejectPromise is a shorthand for a sequence of algorithm steps that use a PromiseCapability Record. An algorithm step of the form:

  1. IfAbruptRejectPromise(value, capability).

means the same thing as:

  1. Assert: value is a Completion Record.
  2. If value is an abrupt completion, then
    1. Perform ? Call(capability.[[Reject]], undefined, « value.[[Value]] »).
    2. Return capability.[[Promise]].
  3. Else,
    1. Set value to ! value.

27.2.1.2 PromiseReaction Records

A PromiseReaction Record is a Record value used to store information about how a promise should react when it becomes resolved or rejected with a given value. PromiseReaction Records are created by the PerformPromiseThen abstract operation, and are used by the Abstract Closure returned by NewPromiseReactionJob.

PromiseReaction Records have the fields listed in Table 91.

Table 91: PromiseReaction Record Fields
Field Name Value Meaning
[[Capability]] a PromiseCapability Record or undefined The capabilities of the promise for which this record provides a reaction handler.
[[Type]] fulfill or reject The [[Type]] is used when [[Handler]] is empty to allow for behaviour specific to the settlement type.
[[Handler]] a JobCallback Record or empty The function that should be applied to the incoming value, and whose return value will govern what happens to the derived promise. If [[Handler]] is empty, a function that depends on the value of [[Type]] will be used instead.

27.2.1.3 CreateResolvingFunctions ( promise )

The abstract operation CreateResolvingFunctions takes argument promise (a Promise) and returns a Record with fields [[Resolve]] (a function object) and [[Reject]] (a function object). It performs the following steps when called:

  1. Let alreadyResolved be the Record { [[Value]]: false }.
  2. Let stepsResolve be the algorithm steps defined in Promise Resolve Functions.
  3. Let lengthResolve be the number of non-optional parameters of the function definition in Promise Resolve Functions.
  4. Let resolve be CreateBuiltinFunction(stepsResolve, lengthResolve, "", « [[Promise]], [[AlreadyResolved]] »).
  5. Set resolve.[[Promise]] to promise.
  6. Set resolve.[[AlreadyResolved]] to alreadyResolved.
  7. Let stepsReject be the algorithm steps defined in Promise Reject Functions.
  8. Let lengthReject be the number of non-optional parameters of the function definition in Promise Reject Functions.
  9. Let reject be CreateBuiltinFunction(stepsReject, lengthReject, "", « [[Promise]], [[AlreadyResolved]] »).
  10. Set reject.[[Promise]] to promise.
  11. Set reject.[[AlreadyResolved]] to alreadyResolved.
  12. Return the Record { [[Resolve]]: resolve, [[Reject]]: reject }.

27.2.1.3.1 Promise Reject Functions

A promise reject function is an anonymous built-in function that has [[Promise]] and [[AlreadyResolved]] internal slots.

When a promise reject function is called with argument reason, the following steps are taken:

  1. Let F be the active function object.
  2. Assert: F has a [[Promise]] internal slot whose value is an Object.
  3. Let promise be F.[[Promise]].
  4. Let alreadyResolved be F.[[AlreadyResolved]].
  5. If alreadyResolved.[[Value]] is true, return undefined.
  6. Set alreadyResolved.[[Value]] to true.
  7. Perform RejectPromise(promise, reason).
  8. Return undefined.

The "length" property of a promise reject function is 1𝔽.

27.2.1.3.2 Promise Resolve Functions

A promise resolve function is an anonymous built-in function that has [[Promise]] and [[AlreadyResolved]] internal slots.

When a promise resolve function is called with argument resolution, the following steps are taken:

  1. Let F be the active function object.
  2. Assert: F has a [[Promise]] internal slot whose value is an Object.
  3. Let promise be F.[[Promise]].
  4. Let alreadyResolved be F.[[AlreadyResolved]].
  5. If alreadyResolved.[[Value]] is true, return undefined.
  6. Set alreadyResolved.[[Value]] to true.
  7. If SameValue(resolution, promise) is true, then
    1. Let selfResolutionError be a newly created TypeError object.
    2. Perform RejectPromise(promise, selfResolutionError).
    3. Return undefined.
  8. If resolution is not an Object, then
    1. Perform FulfillPromise(promise, resolution).
    2. Return undefined.
  9. Let then be Completion(Get(resolution, "then")).
  10. If then is an abrupt completion, then
    1. Perform RejectPromise(promise, then.[[Value]]).
    2. Return undefined.
  11. Let thenAction be then.[[Value]].
  12. If IsCallable(thenAction) is false, then
    1. Perform FulfillPromise(promise, resolution).
    2. Return undefined.
  13. Let thenJobCallback be HostMakeJobCallback(thenAction).
  14. Let job be NewPromiseResolveThenableJob(promise, resolution, thenJobCallback).
  15. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
  16. Return undefined.

The "length" property of a promise resolve function is 1𝔽.

27.2.1.4 FulfillPromise ( promise, value )

The abstract operation FulfillPromise takes arguments promise (a Promise) and value (an ECMAScript language value) and returns unused. It performs the following steps when called:

  1. Assert: The value of promise.[[PromiseState]] is pending.
  2. Let reactions be promise.[[PromiseFulfillReactions]].
  3. Set promise.[[PromiseResult]] to value.
  4. Set promise.[[PromiseFulfillReactions]] to undefined.
  5. Set promise.[[PromiseRejectReactions]] to undefined.
  6. Set promise.[[PromiseState]] to fulfilled.
  7. Perform TriggerPromiseReactions(reactions, value).
  8. Return unused.

27.2.1.5 NewPromiseCapability ( C )

The abstract operation NewPromiseCapability takes argument C (an ECMAScript language value) and returns either a normal completion containing a PromiseCapability Record or a throw completion. It attempts to use C as a constructor in the fashion of the built-in Promise constructor to create a promise and extract its resolve and reject functions. The promise plus the resolve and reject functions are used to initialize a new PromiseCapability Record. It performs the following steps when called:

  1. If IsConstructor(C) is false, throw a TypeError exception.
  2. NOTE: C is assumed to be a constructor function that supports the parameter conventions of the Promise constructor (see 27.2.3.1).
  3. Let resolvingFunctions be the Record { [[Resolve]]: undefined, [[Reject]]: undefined }.
  4. Let executorClosure be a new Abstract Closure with parameters (resolve, reject) that captures resolvingFunctions and performs the following steps when called:
    1. If resolvingFunctions.[[Resolve]] is not undefined, throw a TypeError exception.
    2. If resolvingFunctions.[[Reject]] is not undefined, throw a TypeError exception.
    3. Set resolvingFunctions.[[Resolve]] to resolve.
    4. Set resolvingFunctions.[[Reject]] to reject.
    5. Return undefined.
  5. Let executor be CreateBuiltinFunction(executorClosure, 2, "", « »).
  6. Let promise be ? Construct(C, « executor »).
  7. If IsCallable(resolvingFunctions.[[Resolve]]) is false, throw a TypeError exception.
  8. If IsCallable(resolvingFunctions.[[Reject]]) is false, throw a TypeError exception.
  9. Return the PromiseCapability Record { [[Promise]]: promise, [[Resolve]]: resolvingFunctions.[[Resolve]], [[Reject]]: resolvingFunctions.[[Reject]] }.
Note

This abstract operation supports Promise subclassing, as it is generic on any constructor that calls a passed executor function argument in the same way as the Promise constructor. It is used to generalize static methods of the Promise constructor to any subclass.

27.2.1.6 IsPromise ( x )

The abstract operation IsPromise takes argument x (an ECMAScript language value) and returns a Boolean. It checks for the promise brand on an object. It performs the following steps when called:

  1. If x is not an Object, return false.
  2. If x does not have a [[PromiseState]] internal slot, return false.
  3. Return true.

27.2.1.7 RejectPromise ( promise, reason )

The abstract operation RejectPromise takes arguments promise (a Promise) and reason (an ECMAScript language value) and returns unused. It performs the following steps when called:

  1. Assert: The value of promise.[[PromiseState]] is pending.
  2. Let reactions be promise.[[PromiseRejectReactions]].
  3. Set promise.[[PromiseResult]] to reason.
  4. Set promise.[[PromiseFulfillReactions]] to undefined.
  5. Set promise.[[PromiseRejectReactions]] to undefined.
  6. Set promise.[[PromiseState]] to rejected.
  7. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "reject").
  8. Perform TriggerPromiseReactions(reactions, reason).
  9. Return unused.

27.2.1.8 TriggerPromiseReactions ( reactions, argument )

The abstract operation TriggerPromiseReactions takes arguments reactions (a List of PromiseReaction Records) and argument (an ECMAScript language value) and returns unused. It enqueues a new Job for each record in reactions. Each such Job processes the [[Type]] and [[Handler]] of the PromiseReaction Record, and if the [[Handler]] is not empty, calls it passing the given argument. If the [[Handler]] is empty, the behaviour is determined by the [[Type]]. It performs the following steps when called:

  1. For each element reaction of reactions, do
    1. Let job be NewPromiseReactionJob(reaction, argument).
    2. Perform HostEnqueuePromiseJob(job.[[Job]], job.[[Realm]]).
  2. Return unused.

27.2.1.9 HostPromiseRejectionTracker ( promise, operation )

The host-defined abstract operation HostPromiseRejectionTracker takes arguments promise (a Promise) and operation ("reject" or "handle") and returns unused. It allows host environments to track promise rejections.

The default implementation of HostPromiseRejectionTracker is to return unused.

Note 1

HostPromiseRejectionTracker is called in two scenarios:

  • When a promise is rejected without any handlers, it is called with its operation argument set to "reject".
  • When a handler is added to a rejected promise for the first time, it is called with its operation argument set to "handle".

A typical implementation of HostPromiseRejectionTracker might try to notify developers of unhandled rejections, while also being careful to notify them if such previous notifications are later invalidated by new handlers being attached.

Note 2

If operation is "handle", an implementation should not hold a reference to promise in a way that would interfere with garbage collection. An implementation may hold a reference to promise if operation is "reject", since it is expected that rejections will be rare and not on hot code paths.

27.2.2 Promise Jobs

27.2.2.1 NewPromiseReactionJob ( reaction, argument )

The abstract operation NewPromiseReactionJob takes arguments reaction (a PromiseReaction Record) and argument (an ECMAScript language value) and returns a Record with fields [[Job]] (a Job Abstract Closure) and [[Realm]] (a Realm Record or null). It returns a new Job Abstract Closure that applies the appropriate handler to the incoming value, and uses the handler's return value to resolve or reject the derived promise associated with that handler. It performs the following steps when called:

  1. Let job be a new Job Abstract Closure with no parameters that captures reaction and argument and performs the following steps when called:
    1. Let promiseCapability be reaction.[[Capability]].
    2. Let type be reaction.[[Type]].
    3. Let handler be reaction.[[Handler]].
    4. If handler is empty, then
      1. If type is fulfill, then
        1. Let handlerResult be NormalCompletion(argument).
      2. Else,
        1. Assert: type is reject.
        2. Let handlerResult be ThrowCompletion(argument).
    5. Else,
      1. Let handlerResult be Completion(HostCallJobCallback(handler, undefined, « argument »)).
    6. If promiseCapability is undefined, then
      1. Assert: handlerResult is not an abrupt completion.
      2. Return empty.
    7. Assert: promiseCapability is a PromiseCapability Record.
    8. If handlerResult is an abrupt completion, then
      1. Return ? Call(promiseCapability.[[Reject]], undefined, « handlerResult.[[Value]] »).
    9. Else,
      1. Return ? Call(promiseCapability.[[Resolve]], undefined, « handlerResult.[[Value]] »).
  2. Let handlerRealm be null.
  3. If reaction.[[Handler]] is not empty, then
    1. Let getHandlerRealmResult be Completion(GetFunctionRealm(reaction.[[Handler]].[[Callback]])).
    2. If getHandlerRealmResult is a normal completion, set handlerRealm to getHandlerRealmResult.[[Value]].
    3. Else, set handlerRealm to the current Realm Record.
    4. NOTE: handlerRealm is never null unless the handler is undefined. When the handler is a revoked Proxy and no ECMAScript code runs, handlerRealm is used to create error objects.
  4. Return the Record { [[Job]]: job, [[Realm]]: handlerRealm }.

27.2.2.2 NewPromiseResolveThenableJob ( promiseToResolve, thenable, then )

The abstract operation NewPromiseResolveThenableJob takes arguments promiseToResolve (a Promise), thenable (an Object), and then (a JobCallback Record) and returns a Record with fields [[Job]] (a Job Abstract Closure) and [[Realm]] (a Realm Record). It performs the following steps when called:

  1. Let job be a new Job Abstract Closure with no parameters that captures promiseToResolve, thenable, and then and performs the following steps when called:
    1. Let resolvingFunctions be CreateResolvingFunctions(promiseToResolve).
    2. Let thenCallResult be Completion(HostCallJobCallback(then, thenable, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
    3. If thenCallResult is an abrupt completion, then
      1. Return ? Call(resolvingFunctions.[[Reject]], undefined, « thenCallResult.[[Value]] »).
    4. Return ! thenCallResult.
  2. Let getThenRealmResult be Completion(GetFunctionRealm(then.[[Callback]])).
  3. If getThenRealmResult is a normal completion, let thenRealm be getThenRealmResult.[[Value]].
  4. Else, let thenRealm be the current Realm Record.
  5. NOTE: thenRealm is never null. When then.[[Callback]] is a revoked Proxy and no code runs, thenRealm is used to create error objects.
  6. Return the Record { [[Job]]: job, [[Realm]]: thenRealm }.
Note

This Job uses the supplied thenable and its then method to resolve the given promise. This process must take place as a Job to ensure that the evaluation of the then method occurs after evaluation of any surrounding code has completed.

27.2.3 The Promise Constructor

The Promise constructor:

  • is %Promise%.
  • is the initial value of the "Promise" property of the global object.
  • creates and initializes a new Promise when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.
  • may be used as the value in an extends clause of a class definition. Subclass constructors that intend to inherit the specified Promise behaviour must include a super call to the Promise constructor to create and initialize the subclass instance with the internal state necessary to support the Promise and Promise.prototype built-in methods.

27.2.3.1 Promise ( executor )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. If IsCallable(executor) is false, throw a TypeError exception.
  3. Let promise be ? OrdinaryCreateFromConstructor(NewTarget, "%Promise.prototype%", « [[PromiseState]], [[PromiseResult]], [[PromiseFulfillReactions]], [[PromiseRejectReactions]], [[PromiseIsHandled]] »).
  4. Set promise.[[PromiseState]] to pending.
  5. Set promise.[[PromiseResult]] to empty.
  6. Set promise.[[PromiseFulfillReactions]] to a new empty List.
  7. Set promise.[[PromiseRejectReactions]] to a new empty List.
  8. Set promise.[[PromiseIsHandled]] to false.
  9. Let resolvingFunctions be CreateResolvingFunctions(promise).
  10. Let completion be Completion(Call(executor, undefined, « resolvingFunctions.[[Resolve]], resolvingFunctions.[[Reject]] »)).
  11. If completion is an abrupt completion, then
    1. Perform ? Call(resolvingFunctions.[[Reject]], undefined, « completion.[[Value]] »).
  12. Return promise.
Note

The executor argument must be a function object. It is called for initiating and reporting completion of the possibly deferred action represented by this Promise. The executor is called with two arguments: resolve and reject. These are functions that may be used by the executor function to report eventual completion or failure of the deferred computation. Returning from the executor function does not mean that the deferred action has been completed but only that the request to eventually perform the deferred action has been accepted.

The resolve function that is passed to an executor function accepts a single argument. The executor code may eventually call the resolve function to indicate that it wishes to resolve the associated Promise. The argument passed to the resolve function represents the eventual value of the deferred action and can be either the actual fulfillment value or another promise which will provide the value if it is fulfilled.

The reject function that is passed to an executor function accepts a single argument. The executor code may eventually call the reject function to indicate that the associated Promise is rejected and will never be fulfilled. The argument passed to the reject function is used as the rejection value of the promise. Typically it will be an Error object.

The resolve and reject functions passed to an executor function by the Promise constructor have the capability to actually resolve and reject the associated promise. Subclasses may have different constructor behaviour that passes in customized values for resolve and reject.

27.2.4 Properties of the Promise Constructor

The Promise constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • has the following properties:

27.2.4.1 Promise.all ( iterable )

This function returns a new promise which is fulfilled with an array of fulfillment values for the passed promises, or rejects with the reason of the first passed promise that rejects. It resolves all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let promiseResolve be Completion(GetPromiseResolve(C)).
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
  5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
  7. Let result be Completion(PerformPromiseAll(iteratorRecord, C, promiseCapability, promiseResolve)).
  8. If result is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
    2. IfAbruptRejectPromise(result, promiseCapability).
  9. Return ! result.
Note

This function requires its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.1.1 GetPromiseResolve ( promiseConstructor )

The abstract operation GetPromiseResolve takes argument promiseConstructor (a constructor) and returns either a normal completion containing a function object or a throw completion. It performs the following steps when called:

  1. Let promiseResolve be ? Get(promiseConstructor, "resolve").
  2. If IsCallable(promiseResolve) is false, throw a TypeError exception.
  3. Return promiseResolve.

27.2.4.1.2 PerformPromiseAll ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAll takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let values be a new empty List.
  2. Let remainingElementsCount be the Record { [[Value]]: 1 }.
  3. Let index be 0.
  4. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
      2. If remainingElementsCount.[[Value]] = 0, then
        1. Let valuesArray be CreateArrayFromList(values).
        2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
      3. Return resultCapability.[[Promise]].
    3. Append undefined to values.
    4. Let nextPromise be ? Call(promiseResolve, constructor, « next »).
    5. Let steps be the algorithm steps defined in Promise.all Resolve Element Functions.
    6. Let length be the number of non-optional parameters of the function definition in Promise.all Resolve Element Functions.
    7. Let onFulfilled be CreateBuiltinFunction(steps, length, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
    8. Set onFulfilled.[[AlreadyCalled]] to false.
    9. Set onFulfilled.[[Index]] to index.
    10. Set onFulfilled.[[Values]] to values.
    11. Set onFulfilled.[[Capability]] to resultCapability.
    12. Set onFulfilled.[[RemainingElements]] to remainingElementsCount.
    13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
    14. Perform ? Invoke(nextPromise, "then", « onFulfilled, resultCapability.[[Reject]] »).
    15. Set index to index + 1.

27.2.4.1.3 Promise.all Resolve Element Functions

A Promise.all resolve element function is an anonymous built-in function that is used to resolve a specific Promise.all element. Each Promise.all resolve element function has [[Index]], [[Values]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.

When a Promise.all resolve element function is called with argument x, the following steps are taken:

  1. Let F be the active function object.
  2. If F.[[AlreadyCalled]] is true, return undefined.
  3. Set F.[[AlreadyCalled]] to true.
  4. Let index be F.[[Index]].
  5. Let values be F.[[Values]].
  6. Let promiseCapability be F.[[Capability]].
  7. Let remainingElementsCount be F.[[RemainingElements]].
  8. Set values[index] to x.
  9. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
  10. If remainingElementsCount.[[Value]] = 0, then
    1. Let valuesArray be CreateArrayFromList(values).
    2. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
  11. Return undefined.

The "length" property of a Promise.all resolve element function is 1𝔽.

27.2.4.2 Promise.allSettled ( iterable )

This function returns a promise that is fulfilled with an array of promise state snapshots, but only after all the original promises have settled, i.e. become either fulfilled or rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let promiseResolve be Completion(GetPromiseResolve(C)).
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
  5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
  7. Let result be Completion(PerformPromiseAllSettled(iteratorRecord, C, promiseCapability, promiseResolve)).
  8. If result is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
    2. IfAbruptRejectPromise(result, promiseCapability).
  9. Return ! result.
Note

This function requires its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.2.1 PerformPromiseAllSettled ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAllSettled takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let values be a new empty List.
  2. Let remainingElementsCount be the Record { [[Value]]: 1 }.
  3. Let index be 0.
  4. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
      2. If remainingElementsCount.[[Value]] = 0, then
        1. Let valuesArray be CreateArrayFromList(values).
        2. Perform ? Call(resultCapability.[[Resolve]], undefined, « valuesArray »).
      3. Return resultCapability.[[Promise]].
    3. Append undefined to values.
    4. Let nextPromise be ? Call(promiseResolve, constructor, « next »).
    5. Let stepsFulfilled be the algorithm steps defined in Promise.allSettled Resolve Element Functions.
    6. Let lengthFulfilled be the number of non-optional parameters of the function definition in Promise.allSettled Resolve Element Functions.
    7. Let onFulfilled be CreateBuiltinFunction(stepsFulfilled, lengthFulfilled, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
    8. Let alreadyCalled be the Record { [[Value]]: false }.
    9. Set onFulfilled.[[AlreadyCalled]] to alreadyCalled.
    10. Set onFulfilled.[[Index]] to index.
    11. Set onFulfilled.[[Values]] to values.
    12. Set onFulfilled.[[Capability]] to resultCapability.
    13. Set onFulfilled.[[RemainingElements]] to remainingElementsCount.
    14. Let stepsRejected be the algorithm steps defined in Promise.allSettled Reject Element Functions.
    15. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.allSettled Reject Element Functions.
    16. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Values]], [[Capability]], [[RemainingElements]] »).
    17. Set onRejected.[[AlreadyCalled]] to alreadyCalled.
    18. Set onRejected.[[Index]] to index.
    19. Set onRejected.[[Values]] to values.
    20. Set onRejected.[[Capability]] to resultCapability.
    21. Set onRejected.[[RemainingElements]] to remainingElementsCount.
    22. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
    23. Perform ? Invoke(nextPromise, "then", « onFulfilled, onRejected »).
    24. Set index to index + 1.

27.2.4.2.2 Promise.allSettled Resolve Element Functions

A Promise.allSettled resolve element function is an anonymous built-in function that is used to resolve a specific Promise.allSettled element. Each Promise.allSettled resolve element function has [[Index]], [[Values]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.

When a Promise.allSettled resolve element function is called with argument x, the following steps are taken:

  1. Let F be the active function object.
  2. Let alreadyCalled be F.[[AlreadyCalled]].
  3. If alreadyCalled.[[Value]] is true, return undefined.
  4. Set alreadyCalled.[[Value]] to true.
  5. Let index be F.[[Index]].
  6. Let values be F.[[Values]].
  7. Let promiseCapability be F.[[Capability]].
  8. Let remainingElementsCount be F.[[RemainingElements]].
  9. Let obj be OrdinaryObjectCreate(%Object.prototype%).
  10. Perform ! CreateDataPropertyOrThrow(obj, "status", "fulfilled").
  11. Perform ! CreateDataPropertyOrThrow(obj, "value", x).
  12. Set values[index] to obj.
  13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
  14. If remainingElementsCount.[[Value]] = 0, then
    1. Let valuesArray be CreateArrayFromList(values).
    2. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
  15. Return undefined.

The "length" property of a Promise.allSettled resolve element function is 1𝔽.

27.2.4.2.3 Promise.allSettled Reject Element Functions

A Promise.allSettled reject element function is an anonymous built-in function that is used to reject a specific Promise.allSettled element. Each Promise.allSettled reject element function has [[Index]], [[Values]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.

When a Promise.allSettled reject element function is called with argument x, the following steps are taken:

  1. Let F be the active function object.
  2. Let alreadyCalled be F.[[AlreadyCalled]].
  3. If alreadyCalled.[[Value]] is true, return undefined.
  4. Set alreadyCalled.[[Value]] to true.
  5. Let index be F.[[Index]].
  6. Let values be F.[[Values]].
  7. Let promiseCapability be F.[[Capability]].
  8. Let remainingElementsCount be F.[[RemainingElements]].
  9. Let obj be OrdinaryObjectCreate(%Object.prototype%).
  10. Perform ! CreateDataPropertyOrThrow(obj, "status", "rejected").
  11. Perform ! CreateDataPropertyOrThrow(obj, "reason", x).
  12. Set values[index] to obj.
  13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
  14. If remainingElementsCount.[[Value]] = 0, then
    1. Let valuesArray be CreateArrayFromList(values).
    2. Return ? Call(promiseCapability.[[Resolve]], undefined, « valuesArray »).
  15. Return undefined.

The "length" property of a Promise.allSettled reject element function is 1𝔽.

27.2.4.3 Promise.any ( iterable )

This function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError holding the rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let promiseResolve be Completion(GetPromiseResolve(C)).
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
  5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
  7. Let result be Completion(PerformPromiseAny(iteratorRecord, C, promiseCapability, promiseResolve)).
  8. If result is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
    2. IfAbruptRejectPromise(result, promiseCapability).
  9. Return ! result.
Note

This function requires its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.3.1 PerformPromiseAny ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseAny takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let errors be a new empty List.
  2. Let remainingElementsCount be the Record { [[Value]]: 1 }.
  3. Let index be 0.
  4. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
      2. If remainingElementsCount.[[Value]] = 0, then
        1. Let error be a newly created AggregateError object.
        2. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
        3. Return ThrowCompletion(error).
      3. Return resultCapability.[[Promise]].
    3. Append undefined to errors.
    4. Let nextPromise be ? Call(promiseResolve, constructor, « next »).
    5. Let stepsRejected be the algorithm steps defined in Promise.any Reject Element Functions.
    6. Let lengthRejected be the number of non-optional parameters of the function definition in Promise.any Reject Element Functions.
    7. Let onRejected be CreateBuiltinFunction(stepsRejected, lengthRejected, "", « [[AlreadyCalled]], [[Index]], [[Errors]], [[Capability]], [[RemainingElements]] »).
    8. Set onRejected.[[AlreadyCalled]] to false.
    9. Set onRejected.[[Index]] to index.
    10. Set onRejected.[[Errors]] to errors.
    11. Set onRejected.[[Capability]] to resultCapability.
    12. Set onRejected.[[RemainingElements]] to remainingElementsCount.
    13. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] + 1.
    14. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], onRejected »).
    15. Set index to index + 1.

27.2.4.3.2 Promise.any Reject Element Functions

A Promise.any reject element function is an anonymous built-in function that is used to reject a specific Promise.any element. Each Promise.any reject element function has [[Index]], [[Errors]], [[Capability]], [[RemainingElements]], and [[AlreadyCalled]] internal slots.

When a Promise.any reject element function is called with argument x, the following steps are taken:

  1. Let F be the active function object.
  2. If F.[[AlreadyCalled]] is true, return undefined.
  3. Set F.[[AlreadyCalled]] to true.
  4. Let index be F.[[Index]].
  5. Let errors be F.[[Errors]].
  6. Let promiseCapability be F.[[Capability]].
  7. Let remainingElementsCount be F.[[RemainingElements]].
  8. Set errors[index] to x.
  9. Set remainingElementsCount.[[Value]] to remainingElementsCount.[[Value]] - 1.
  10. If remainingElementsCount.[[Value]] = 0, then
    1. Let error be a newly created AggregateError object.
    2. Perform ! DefinePropertyOrThrow(error, "errors", PropertyDescriptor { [[Configurable]]: true, [[Enumerable]]: false, [[Writable]]: true, [[Value]]: CreateArrayFromList(errors) }).
    3. Return ? Call(promiseCapability.[[Reject]], undefined, « error »).
  11. Return undefined.

The "length" property of a Promise.any reject element function is 1𝔽.

27.2.4.4 Promise.prototype

The initial value of Promise.prototype is the Promise prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.2.4.5 Promise.race ( iterable )

This function returns a new promise which is settled in the same way as the first passed promise to settle. It resolves all elements of the passed iterable to promises as it runs this algorithm.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let promiseResolve be Completion(GetPromiseResolve(C)).
  4. IfAbruptRejectPromise(promiseResolve, promiseCapability).
  5. Let iteratorRecord be Completion(GetIterator(iterable, sync)).
  6. IfAbruptRejectPromise(iteratorRecord, promiseCapability).
  7. Let result be Completion(PerformPromiseRace(iteratorRecord, C, promiseCapability, promiseResolve)).
  8. If result is an abrupt completion, then
    1. If iteratorRecord.[[Done]] is false, set result to Completion(IteratorClose(iteratorRecord, result)).
    2. IfAbruptRejectPromise(result, promiseCapability).
  9. Return ! result.
Note 1

If the iterable argument yields no values or if none of the promises yielded by iterable ever settle, then the pending promise returned by this method will never be settled.

Note 2

This function expects its this value to be a constructor function that supports the parameter conventions of the Promise constructor. It also expects that its this value provides a resolve method.

27.2.4.5.1 PerformPromiseRace ( iteratorRecord, constructor, resultCapability, promiseResolve )

The abstract operation PerformPromiseRace takes arguments iteratorRecord (an Iterator Record), constructor (a constructor), resultCapability (a PromiseCapability Record), and promiseResolve (a function object) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Repeat,
    1. Let next be ? IteratorStepValue(iteratorRecord).
    2. If next is done, then
      1. Return resultCapability.[[Promise]].
    3. Let nextPromise be ? Call(promiseResolve, constructor, « next »).
    4. Perform ? Invoke(nextPromise, "then", « resultCapability.[[Resolve]], resultCapability.[[Reject]] »).

27.2.4.6 Promise.reject ( r )

This function returns a new promise rejected with the passed argument.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Perform ? Call(promiseCapability.[[Reject]], undefined, « r »).
  4. Return promiseCapability.[[Promise]].
Note

This function expects its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.7 Promise.resolve ( x )

This function returns either a new promise resolved with the passed argument, or the argument itself if the argument is a promise produced by this constructor.

  1. Let C be the this value.
  2. If C is not an Object, throw a TypeError exception.
  3. Return ? PromiseResolve(C, x).
Note

This function expects its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.7.1 PromiseResolve ( C, x )

The abstract operation PromiseResolve takes arguments C (an Object) and x (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or a throw completion. It returns a new promise resolved with x. It performs the following steps when called:

  1. If IsPromise(x) is true, then
    1. Let xConstructor be ? Get(x, "constructor").
    2. If SameValue(xConstructor, C) is true, return x.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Perform ? Call(promiseCapability.[[Resolve]], undefined, « x »).
  4. Return promiseCapability.[[Promise]].

27.2.4.8 Promise.try ( callback, ...args )

This function performs the following steps when called:

  1. Let C be the this value.
  2. If C is not an Object, throw a TypeError exception.
  3. Let promiseCapability be ? NewPromiseCapability(C).
  4. Let status be Completion(Call(callback, undefined, args)).
  5. If status is an abrupt completion, then
    1. Perform ? Call(promiseCapability.[[Reject]], undefined, « status.[[Value]] »).
  6. Else,
    1. Perform ? Call(promiseCapability.[[Resolve]], undefined, « status.[[Value]] »).
  7. Return promiseCapability.[[Promise]].
Note

This function expects its this value to be a constructor function that supports the parameter conventions of the Promise constructor.

27.2.4.9 Promise.withResolvers ( )

This function returns an object with three properties: a new promise together with the resolve and reject functions associated with it.

  1. Let C be the this value.
  2. Let promiseCapability be ? NewPromiseCapability(C).
  3. Let obj be OrdinaryObjectCreate(%Object.prototype%).
  4. Perform ! CreateDataPropertyOrThrow(obj, "promise", promiseCapability.[[Promise]]).
  5. Perform ! CreateDataPropertyOrThrow(obj, "resolve", promiseCapability.[[Resolve]]).
  6. Perform ! CreateDataPropertyOrThrow(obj, "reject", promiseCapability.[[Reject]]).
  7. Return obj.

27.2.4.10 get Promise [ %Symbol.species% ]

Promise[%Symbol.species%] is an accessor property whose set accessor function is undefined. Its get accessor function performs the following steps when called:

  1. Return the this value.

The value of the "name" property of this function is "get [Symbol.species]".

Note

Promise prototype methods normally use their this value's constructor to create a derived object. However, a subclass constructor may over-ride that default behaviour by redefining its %Symbol.species% property.

27.2.5 Properties of the Promise Prototype Object

The Promise prototype object:

  • is %Promise.prototype%.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is an ordinary object.
  • does not have a [[PromiseState]] internal slot or any of the other internal slots of Promise instances.

27.2.5.1 Promise.prototype.catch ( onRejected )

This method performs the following steps when called:

  1. Let promise be the this value.
  2. Return ? Invoke(promise, "then", « undefined, onRejected »).

27.2.5.2 Promise.prototype.constructor

The initial value of Promise.prototype.constructor is %Promise%.

27.2.5.3 Promise.prototype.finally ( onFinally )

This method performs the following steps when called:

  1. Let promise be the this value.
  2. If promise is not an Object, throw a TypeError exception.
  3. Let C be ? SpeciesConstructor(promise, %Promise%).
  4. Assert: IsConstructor(C) is true.
  5. If IsCallable(onFinally) is false, then
    1. Let thenFinally be onFinally.
    2. Let catchFinally be onFinally.
  6. Else,
    1. Let thenFinallyClosure be a new Abstract Closure with parameters (value) that captures onFinally and C and performs the following steps when called:
      1. Let result be ? Call(onFinally, undefined).
      2. Let p be ? PromiseResolve(C, result).
      3. Let returnValue be a new Abstract Closure with no parameters that captures value and performs the following steps when called:
        1. Return value.
      4. Let valueThunk be CreateBuiltinFunction(returnValue, 0, "", « »).
      5. Return ? Invoke(p, "then", « valueThunk »).
    2. Let thenFinally be CreateBuiltinFunction(thenFinallyClosure, 1, "", « »).
    3. Let catchFinallyClosure be a new Abstract Closure with parameters (reason) that captures onFinally and C and performs the following steps when called:
      1. Let result be ? Call(onFinally, undefined).
      2. Let p be ? PromiseResolve(C, result).
      3. Let throwReason be a new Abstract Closure with no parameters that captures reason and performs the following steps when called:
        1. Return ThrowCompletion(reason).
      4. Let thrower be CreateBuiltinFunction(throwReason, 0, "", « »).
      5. Return ? Invoke(p, "then", « thrower »).
    4. Let catchFinally be CreateBuiltinFunction(catchFinallyClosure, 1, "", « »).
  7. Return ? Invoke(promise, "then", « thenFinally, catchFinally »).

27.2.5.4 Promise.prototype.then ( onFulfilled, onRejected )

This method performs the following steps when called:

  1. Let promise be the this value.
  2. If IsPromise(promise) is false, throw a TypeError exception.
  3. Let C be ? SpeciesConstructor(promise, %Promise%).
  4. Let resultCapability be ? NewPromiseCapability(C).
  5. Return PerformPromiseThen(promise, onFulfilled, onRejected, resultCapability).

27.2.5.4.1 PerformPromiseThen ( promise, onFulfilled, onRejected [ , resultCapability ] )

The abstract operation PerformPromiseThen takes arguments promise (a Promise), onFulfilled (an ECMAScript language value), and onRejected (an ECMAScript language value) and optional argument resultCapability (a PromiseCapability Record) and returns an ECMAScript language value. It performs the “then” operation on promise using onFulfilled and onRejected as its settlement actions. If resultCapability is passed, the result is stored by updating resultCapability's promise. If it is not passed, then PerformPromiseThen is being called by a specification-internal operation where the result does not matter. It performs the following steps when called:

  1. Assert: IsPromise(promise) is true.
  2. If resultCapability is not present, then
    1. Set resultCapability to undefined.
  3. If IsCallable(onFulfilled) is false, then
    1. Let onFulfilledJobCallback be empty.
  4. Else,
    1. Let onFulfilledJobCallback be HostMakeJobCallback(onFulfilled).
  5. If IsCallable(onRejected) is false, then
    1. Let onRejectedJobCallback be empty.
  6. Else,
    1. Let onRejectedJobCallback be HostMakeJobCallback(onRejected).
  7. Let fulfillReaction be the PromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: fulfill, [[Handler]]: onFulfilledJobCallback }.
  8. Let rejectReaction be the PromiseReaction Record { [[Capability]]: resultCapability, [[Type]]: reject, [[Handler]]: onRejectedJobCallback }.
  9. If promise.[[PromiseState]] is pending, then
    1. Append fulfillReaction to promise.[[PromiseFulfillReactions]].
    2. Append rejectReaction to promise.[[PromiseRejectReactions]].
  10. Else if promise.[[PromiseState]] is fulfilled, then
    1. Let value be promise.[[PromiseResult]].
    2. Let fulfillJob be NewPromiseReactionJob(fulfillReaction, value).
    3. Perform HostEnqueuePromiseJob(fulfillJob.[[Job]], fulfillJob.[[Realm]]).
  11. Else,
    1. Assert: The value of promise.[[PromiseState]] is rejected.
    2. Let reason be promise.[[PromiseResult]].
    3. If promise.[[PromiseIsHandled]] is false, perform HostPromiseRejectionTracker(promise, "handle").
    4. Let rejectJob be NewPromiseReactionJob(rejectReaction, reason).
    5. Perform HostEnqueuePromiseJob(rejectJob.[[Job]], rejectJob.[[Realm]]).
  12. Set promise.[[PromiseIsHandled]] to true.
  13. If resultCapability is undefined, then
    1. Return undefined.
  14. Else,
    1. Return resultCapability.[[Promise]].

27.2.5.5 Promise.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "Promise".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.2.6 Properties of Promise Instances

Promise instances are ordinary objects that inherit properties from the Promise prototype object (the intrinsic, %Promise.prototype%). Promise instances are initially created with the internal slots described in Table 92.

Table 92: Internal Slots of Promise Instances
Internal Slot Type Description
[[PromiseState]] pending, fulfilled, or rejected Governs how a promise will react to incoming calls to its then method.
[[PromiseResult]] an ECMAScript language value or empty The value with which the promise has been fulfilled or rejected, if any. empty if and only if the [[PromiseState]] is pending.
[[PromiseFulfillReactions]] a List of PromiseReaction Records Records to be processed when/if the promise transitions from the pending state to the fulfilled state.
[[PromiseRejectReactions]] a List of PromiseReaction Records Records to be processed when/if the promise transitions from the pending state to the rejected state.
[[PromiseIsHandled]] a Boolean Indicates whether the promise has ever had a fulfillment or rejection handler; used in unhandled rejection tracking.

27.3 GeneratorFunction Objects

GeneratorFunctions are functions that are usually created by evaluating GeneratorDeclarations, GeneratorExpressions, and GeneratorMethods. They may also be created by calling the %GeneratorFunction% intrinsic.

Figure 6 (Informative): Generator Objects Relationships
A staggering variety of boxes and arrows.

27.3.1 The GeneratorFunction Constructor

The GeneratorFunction constructor:

  • is %GeneratorFunction%.
  • is a subclass of Function.
  • creates and initializes a new GeneratorFunction when called as a function rather than as a constructor. Thus the function call GeneratorFunction (…) is equivalent to the object creation expression new GeneratorFunction (…) with the same arguments.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified GeneratorFunction behaviour must include a super call to the GeneratorFunction constructor to create and initialize subclass instances with the internal slots necessary for built-in GeneratorFunction behaviour. All ECMAScript syntactic forms for defining generator function objects create direct instances of GeneratorFunction. There is no syntactic means to create instances of GeneratorFunction subclasses.

27.3.1.1 GeneratorFunction ( ...parameterArgs, bodyArg )

The last argument (if any) specifies the body (executable code) of a generator function; any preceding arguments specify formal parameters.

This function performs the following steps when called:

  1. Let C be the active function object.
  2. If bodyArg is not present, set bodyArg to the empty String.
  3. Return ? CreateDynamicFunction(C, NewTarget, generator, parameterArgs, bodyArg).
Note

See NOTE for 20.2.1.1.

27.3.2 Properties of the GeneratorFunction Constructor

The GeneratorFunction constructor:

  • is a standard built-in function object that inherits from the Function constructor.
  • has a [[Prototype]] internal slot whose value is %Function%.
  • has a "length" property whose value is 1𝔽.
  • has a "name" property whose value is "GeneratorFunction".
  • has the following properties:

27.3.2.1 GeneratorFunction.prototype

The initial value of GeneratorFunction.prototype is the GeneratorFunction prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.3.3 Properties of the GeneratorFunction Prototype Object

The GeneratorFunction prototype object:

27.3.3.1 GeneratorFunction.prototype.constructor

The initial value of GeneratorFunction.prototype.constructor is %GeneratorFunction%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.3.3.2 GeneratorFunction.prototype.prototype

The initial value of GeneratorFunction.prototype.prototype is %GeneratorPrototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.3.3.3 GeneratorFunction.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "GeneratorFunction".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.3.4 GeneratorFunction Instances

Every GeneratorFunction instance is an ECMAScript function object and has the internal slots listed in Table 30. The value of the [[IsClassConstructor]] internal slot for all such instances is false.

Each GeneratorFunction instance has the following own properties:

27.3.4.1 length

The specification for the "length" property of Function instances given in 20.2.4.1 also applies to GeneratorFunction instances.

27.3.4.2 name

The specification for the "name" property of Function instances given in 20.2.4.2 also applies to GeneratorFunction instances.

27.3.4.3 prototype

Whenever a GeneratorFunction instance is created another ordinary object is also created and is the initial value of the generator function's "prototype" property. The value of the prototype property is used to initialize the [[Prototype]] internal slot of a newly created Generator when the generator function object is invoked using [[Call]].

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.

Note

Unlike Function instances, the object that is the value of a GeneratorFunction's "prototype" property does not have a "constructor" property whose value is the GeneratorFunction instance.

27.4 AsyncGeneratorFunction Objects

AsyncGeneratorFunctions are functions that are usually created by evaluating AsyncGeneratorDeclaration, AsyncGeneratorExpression, and AsyncGeneratorMethod syntactic productions. They may also be created by calling the %AsyncGeneratorFunction% intrinsic.

27.4.1 The AsyncGeneratorFunction Constructor

The AsyncGeneratorFunction constructor:

  • is %AsyncGeneratorFunction%.
  • is a subclass of Function.
  • creates and initializes a new AsyncGeneratorFunction when called as a function rather than as a constructor. Thus the function call AsyncGeneratorFunction (...) is equivalent to the object creation expression new AsyncGeneratorFunction (...) with the same arguments.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified AsyncGeneratorFunction behaviour must include a super call to the AsyncGeneratorFunction constructor to create and initialize subclass instances with the internal slots necessary for built-in AsyncGeneratorFunction behaviour. All ECMAScript syntactic forms for defining async generator function objects create direct instances of AsyncGeneratorFunction. There is no syntactic means to create instances of AsyncGeneratorFunction subclasses.

27.4.1.1 AsyncGeneratorFunction ( ...parameterArgs, bodyArg )

The last argument (if any) specifies the body (executable code) of an async generator function; any preceding arguments specify formal parameters.

This function performs the following steps when called:

  1. Let C be the active function object.
  2. If bodyArg is not present, set bodyArg to the empty String.
  3. Return ? CreateDynamicFunction(C, NewTarget, async-generator, parameterArgs, bodyArg).
Note

See NOTE for 20.2.1.1.

27.4.2 Properties of the AsyncGeneratorFunction Constructor

The AsyncGeneratorFunction constructor:

  • is a standard built-in function object that inherits from the Function constructor.
  • has a [[Prototype]] internal slot whose value is %Function%.
  • has a "length" property whose value is 1𝔽.
  • has a "name" property whose value is "AsyncGeneratorFunction".
  • has the following properties:

27.4.2.1 AsyncGeneratorFunction.prototype

The initial value of AsyncGeneratorFunction.prototype is the AsyncGeneratorFunction prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.4.3 Properties of the AsyncGeneratorFunction Prototype Object

The AsyncGeneratorFunction prototype object:

27.4.3.1 AsyncGeneratorFunction.prototype.constructor

The initial value of AsyncGeneratorFunction.prototype.constructor is %AsyncGeneratorFunction%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.4.3.2 AsyncGeneratorFunction.prototype.prototype

The initial value of AsyncGeneratorFunction.prototype.prototype is %AsyncGeneratorPrototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.4.3.3 AsyncGeneratorFunction.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "AsyncGeneratorFunction".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.4.4 AsyncGeneratorFunction Instances

Every AsyncGeneratorFunction instance is an ECMAScript function object and has the internal slots listed in Table 30. The value of the [[IsClassConstructor]] internal slot for all such instances is false.

Each AsyncGeneratorFunction instance has the following own properties:

27.4.4.1 length

The value of the "length" property is an integral Number that indicates the typical number of arguments expected by the AsyncGeneratorFunction. However, the language permits the function to be invoked with some other number of arguments. The behaviour of an AsyncGeneratorFunction when invoked on a number of arguments other than the number specified by its "length" property depends on the function.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.4.4.2 name

The specification for the "name" property of Function instances given in 20.2.4.2 also applies to AsyncGeneratorFunction instances.

27.4.4.3 prototype

Whenever an AsyncGeneratorFunction instance is created, another ordinary object is also created and is the initial value of the async generator function's "prototype" property. The value of the prototype property is used to initialize the [[Prototype]] internal slot of a newly created AsyncGenerator when the generator function object is invoked using [[Call]].

This property has the attributes { [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false }.

Note

Unlike function instances, the object that is the value of an AsyncGeneratorFunction's "prototype" property does not have a "constructor" property whose value is the AsyncGeneratorFunction instance.

27.5 Generator Objects

A Generator is created by calling a generator function and conforms to both the iterator interface and the iterable interface.

Generator instances directly inherit properties from the initial value of the "prototype" property of the generator function that created the instance. Generator instances indirectly inherit properties from %GeneratorPrototype%.

27.5.1 The %GeneratorPrototype% Object

The %GeneratorPrototype% object:

  • is %GeneratorFunction.prototype.prototype%.
  • is an ordinary object.
  • is not a Generator instance and does not have a [[GeneratorState]] internal slot.
  • has a [[Prototype]] internal slot whose value is %Iterator.prototype%.
  • has properties that are indirectly inherited by all Generator instances.

27.5.1.1 %GeneratorPrototype%.constructor

The initial value of %GeneratorPrototype%.constructor is %GeneratorFunction.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.5.1.2 %GeneratorPrototype%.next ( value )

  1. Return ? GeneratorResume(this value, value, empty).

27.5.1.3 %GeneratorPrototype%.return ( value )

This method performs the following steps when called:

  1. Let g be the this value.
  2. Let C be ReturnCompletion(value).
  3. Return ? GeneratorResumeAbrupt(g, C, empty).

27.5.1.4 %GeneratorPrototype%.throw ( exception )

This method performs the following steps when called:

  1. Let g be the this value.
  2. Let C be ThrowCompletion(exception).
  3. Return ? GeneratorResumeAbrupt(g, C, empty).

27.5.1.5 %GeneratorPrototype% [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "Generator".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.5.2 Properties of Generator Instances

Generator instances are initially created with the internal slots described in Table 93.

Table 93: Internal Slots of Generator Instances
Internal Slot Type Description
[[GeneratorState]] suspended-start, suspended-yield, executing, or completed The current execution state of the generator.
[[GeneratorContext]] an execution context The execution context that is used when executing the code of this generator.
[[GeneratorBrand]] a String or empty A brand used to distinguish different kinds of generators. The [[GeneratorBrand]] of generators declared by ECMAScript source text is always empty.

27.5.3 Generator Abstract Operations

27.5.3.1 GeneratorStart ( generator, generatorBody )

The abstract operation GeneratorStart takes arguments generator (a Generator) and generatorBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. Assert: The value of generator.[[GeneratorState]] is suspended-start.
  2. Let genContext be the running execution context.
  3. Set the Generator component of genContext to generator.
  4. Let closure be a new Abstract Closure with no parameters that captures generatorBody and performs the following steps when called:
    1. Let acGenContext be the running execution context.
    2. Let acGenerator be the Generator component of acGenContext.
    3. If generatorBody is a Parse Node, then
      1. Let result be Completion(Evaluation of generatorBody).
    4. Else,
      1. Assert: generatorBody is an Abstract Closure with no parameters.
      2. Let result be Completion(generatorBody()).
    5. Assert: If we return here, the generator either threw an exception or performed either an implicit or explicit return.
    6. Remove acGenContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
    7. Set acGenerator.[[GeneratorState]] to completed.
    8. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with acGenerator can be discarded at this point.
    9. If result is a normal completion, then
      1. Let resultValue be undefined.
    10. Else if result is a return completion, then
      1. Let resultValue be result.[[Value]].
    11. Else,
      1. Assert: result is a throw completion.
      2. Return ? result.
    12. Return CreateIteratorResultObject(resultValue, true).
  5. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context, closure will be called with no arguments.
  6. Set generator.[[GeneratorContext]] to genContext.
  7. Return unused.

27.5.3.2 GeneratorValidate ( generator, generatorBrand )

The abstract operation GeneratorValidate takes arguments generator (an ECMAScript language value) and generatorBrand (a String or empty) and returns either a normal completion containing one of suspended-start, suspended-yield, or completed, or a throw completion. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(generator, [[GeneratorState]]).
  2. Perform ? RequireInternalSlot(generator, [[GeneratorBrand]]).
  3. If generator.[[GeneratorBrand]] is not generatorBrand, throw a TypeError exception.
  4. Assert: generator also has a [[GeneratorContext]] internal slot.
  5. Let state be generator.[[GeneratorState]].
  6. If state is executing, throw a TypeError exception.
  7. Return state.

27.5.3.3 GeneratorResume ( generator, value, generatorBrand )

The abstract operation GeneratorResume takes arguments generator (an ECMAScript language value), value (an ECMAScript language value or empty), and generatorBrand (a String or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let state be ? GeneratorValidate(generator, generatorBrand).
  2. If state is completed, return CreateIteratorResultObject(undefined, true).
  3. Assert: state is either suspended-start or suspended-yield.
  4. Let genContext be generator.[[GeneratorContext]].
  5. Let methodContext be the running execution context.
  6. Suspend methodContext.
  7. Set generator.[[GeneratorState]] to executing.
  8. Push genContext onto the execution context stack; genContext is now the running execution context.
  9. Resume the suspended evaluation of genContext using NormalCompletion(value) as the result of the operation that suspended it. Let result be the value returned by the resumed computation.
  10. Assert: When we return here, genContext has already been removed from the execution context stack and methodContext is the currently running execution context.
  11. Return ? result.

27.5.3.4 GeneratorResumeAbrupt ( generator, abruptCompletion, generatorBrand )

The abstract operation GeneratorResumeAbrupt takes arguments generator (an ECMAScript language value), abruptCompletion (a return completion or a throw completion), and generatorBrand (a String or empty) and returns either a normal completion containing an ECMAScript language value or a throw completion. It performs the following steps when called:

  1. Let state be ? GeneratorValidate(generator, generatorBrand).
  2. If state is suspended-start, then
    1. Set generator.[[GeneratorState]] to completed.
    2. NOTE: Once a generator enters the completed state it never leaves it and its associated execution context is never resumed. Any execution state associated with generator can be discarded at this point.
    3. Set state to completed.
  3. If state is completed, then
    1. If abruptCompletion is a return completion, then
      1. Return CreateIteratorResultObject(abruptCompletion.[[Value]], true).
    2. Return ? abruptCompletion.
  4. Assert: state is suspended-yield.
  5. Let genContext be generator.[[GeneratorContext]].
  6. Let methodContext be the running execution context.
  7. Suspend methodContext.
  8. Set generator.[[GeneratorState]] to executing.
  9. Push genContext onto the execution context stack; genContext is now the running execution context.
  10. Resume the suspended evaluation of genContext using abruptCompletion as the result of the operation that suspended it. Let result be the Completion Record returned by the resumed computation.
  11. Assert: When we return here, genContext has already been removed from the execution context stack and methodContext is the currently running execution context.
  12. Return ? result.

27.5.3.5 GetGeneratorKind ( )

The abstract operation GetGeneratorKind takes no arguments and returns non-generator, sync, or async. It performs the following steps when called:

  1. Let genContext be the running execution context.
  2. If genContext does not have a Generator component, return non-generator.
  3. Let generator be the Generator component of genContext.
  4. If generator has an [[AsyncGeneratorState]] internal slot, return async.
  5. Else, return sync.

27.5.3.6 GeneratorYield ( iteratorResult )

The abstract operation GeneratorYield takes argument iteratorResult (an Object that conforms to the IteratorResult interface) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. Let genContext be the running execution context.
  2. Assert: genContext is the execution context of a generator.
  3. Let generator be the value of the Generator component of genContext.
  4. Assert: GetGeneratorKind() is sync.
  5. Set generator.[[GeneratorState]] to suspended-yield.
  6. Remove genContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
  7. Let callerContext be the running execution context.
  8. Resume callerContext passing NormalCompletion(iteratorResult). If genContext is ever resumed again, let resumptionValue be the Completion Record with which it is resumed.
  9. Assert: If control reaches here, then genContext is the running execution context again.
  10. Return resumptionValue.

27.5.3.7 Yield ( value )

The abstract operation Yield takes argument value (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. Let generatorKind be GetGeneratorKind().
  2. If generatorKind is async, return ? AsyncGeneratorYield(? Await(value)).
  3. Otherwise, return ? GeneratorYield(CreateIteratorResultObject(value, false)).

27.5.3.8 CreateIteratorFromClosure ( closure, generatorBrand, generatorPrototype [ , extraSlots ] )

The abstract operation CreateIteratorFromClosure takes arguments closure (an Abstract Closure with no parameters), generatorBrand (a String or empty), and generatorPrototype (an Object) and optional argument extraSlots (a List of names of internal slots) and returns a Generator. It performs the following steps when called:

  1. NOTE: closure can contain uses of the Yield operation to yield an IteratorResult object.
  2. If extraSlots is not present, set extraSlots to a new empty List.
  3. Let internalSlotsList be the list-concatenation of extraSlots and « [[GeneratorState]], [[GeneratorContext]], [[GeneratorBrand]] ».
  4. Let generator be OrdinaryObjectCreate(generatorPrototype, internalSlotsList).
  5. Set generator.[[GeneratorBrand]] to generatorBrand.
  6. Set generator.[[GeneratorState]] to suspended-start.
  7. Let callerContext be the running execution context.
  8. Let calleeContext be a new execution context.
  9. Set the Function of calleeContext to null.
  10. Set the Realm of calleeContext to the current Realm Record.
  11. Set the ScriptOrModule of calleeContext to callerContext's ScriptOrModule.
  12. If callerContext is not already suspended, suspend callerContext.
  13. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  14. Perform GeneratorStart(generator, closure).
  15. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  16. Return generator.

27.6 AsyncGenerator Objects

An AsyncGenerator is created by calling an async generator function and conforms to both the async iterator interface and the async iterable interface.

AsyncGenerator instances directly inherit properties from the initial value of the "prototype" property of the async generator function that created the instance. AsyncGenerator instances indirectly inherit properties from %AsyncGeneratorPrototype%.

27.6.1 The %AsyncGeneratorPrototype% Object

The %AsyncGeneratorPrototype% object:

  • is %AsyncGeneratorFunction.prototype.prototype%.
  • is an ordinary object.
  • is not an AsyncGenerator instance and does not have an [[AsyncGeneratorState]] internal slot.
  • has a [[Prototype]] internal slot whose value is %AsyncIteratorPrototype%.
  • has properties that are indirectly inherited by all AsyncGenerator instances.

27.6.1.1 %AsyncGeneratorPrototype%.constructor

The initial value of %AsyncGeneratorPrototype%.constructor is %AsyncGeneratorFunction.prototype%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.6.1.2 %AsyncGeneratorPrototype%.next ( value )

  1. Let generator be the this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let result be Completion(AsyncGeneratorValidate(generator, empty)).
  4. IfAbruptRejectPromise(result, promiseCapability).
  5. Let state be generator.[[AsyncGeneratorState]].
  6. If state is completed, then
    1. Let iteratorResult be CreateIteratorResultObject(undefined, true).
    2. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
    3. Return promiseCapability.[[Promise]].
  7. Let completion be NormalCompletion(value).
  8. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
  9. If state is either suspended-start or suspended-yield, then
    1. Perform AsyncGeneratorResume(generator, completion).
  10. Else,
    1. Assert: state is either executing or draining-queue.
  11. Return promiseCapability.[[Promise]].

27.6.1.3 %AsyncGeneratorPrototype%.return ( value )

  1. Let generator be the this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let result be Completion(AsyncGeneratorValidate(generator, empty)).
  4. IfAbruptRejectPromise(result, promiseCapability).
  5. Let completion be ReturnCompletion(value).
  6. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
  7. Let state be generator.[[AsyncGeneratorState]].
  8. If state is either suspended-start or completed, then
    1. Set generator.[[AsyncGeneratorState]] to draining-queue.
    2. Perform AsyncGeneratorAwaitReturn(generator).
  9. Else if state is suspended-yield, then
    1. Perform AsyncGeneratorResume(generator, completion).
  10. Else,
    1. Assert: state is either executing or draining-queue.
  11. Return promiseCapability.[[Promise]].

27.6.1.4 %AsyncGeneratorPrototype%.throw ( exception )

  1. Let generator be the this value.
  2. Let promiseCapability be ! NewPromiseCapability(%Promise%).
  3. Let result be Completion(AsyncGeneratorValidate(generator, empty)).
  4. IfAbruptRejectPromise(result, promiseCapability).
  5. Let state be generator.[[AsyncGeneratorState]].
  6. If state is suspended-start, then
    1. Set generator.[[AsyncGeneratorState]] to completed.
    2. Set state to completed.
  7. If state is completed, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « exception »).
    2. Return promiseCapability.[[Promise]].
  8. Let completion be ThrowCompletion(exception).
  9. Perform AsyncGeneratorEnqueue(generator, completion, promiseCapability).
  10. If state is suspended-yield, then
    1. Perform AsyncGeneratorResume(generator, completion).
  11. Else,
    1. Assert: state is either executing or draining-queue.
  12. Return promiseCapability.[[Promise]].

27.6.1.5 %AsyncGeneratorPrototype% [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "AsyncGenerator".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.6.2 Properties of AsyncGenerator Instances

AsyncGenerator instances are initially created with the internal slots described below:

Table 94: Internal Slots of AsyncGenerator Instances
Internal Slot Type Description
[[AsyncGeneratorState]] suspended-start, suspended-yield, executing, draining-queue, or completed The current execution state of the async generator.
[[AsyncGeneratorContext]] an execution context The execution context that is used when executing the code of this async generator.
[[AsyncGeneratorQueue]] a List of AsyncGeneratorRequest Records Records which represent requests to resume the async generator. Except during state transitions, it is non-empty if and only if [[AsyncGeneratorState]] is either executing or draining-queue.
[[GeneratorBrand]] a String or empty A brand used to distinguish different kinds of async generators. The [[GeneratorBrand]] of async generators declared by ECMAScript source text is always empty.

27.6.3 AsyncGenerator Abstract Operations

27.6.3.1 AsyncGeneratorRequest Records

An AsyncGeneratorRequest is a Record value used to store information about how an async generator should be resumed and contains capabilities for fulfilling or rejecting the corresponding promise.

They have the following fields:

Table 95: AsyncGeneratorRequest Record Fields
Field Name Value Meaning
[[Completion]] a Completion Record The Completion Record which should be used to resume the async generator.
[[Capability]] a PromiseCapability Record The promise capabilities associated with this request.

27.6.3.2 AsyncGeneratorStart ( generator, generatorBody )

The abstract operation AsyncGeneratorStart takes arguments generator (an AsyncGenerator) and generatorBody (a FunctionBody Parse Node or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. Assert: generator.[[AsyncGeneratorState]] is suspended-start.
  2. Let genContext be the running execution context.
  3. Set the Generator component of genContext to generator.
  4. Let closure be a new Abstract Closure with no parameters that captures generatorBody and performs the following steps when called:
    1. Let acGenContext be the running execution context.
    2. Let acGenerator be the Generator component of acGenContext.
    3. If generatorBody is a Parse Node, then
      1. Let result be Completion(Evaluation of generatorBody).
    4. Else,
      1. Assert: generatorBody is an Abstract Closure with no parameters.
      2. Let result be Completion(generatorBody()).
    5. Assert: If we return here, the async generator either threw an exception or performed either an implicit or explicit return.
    6. Remove acGenContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
    7. Set acGenerator.[[AsyncGeneratorState]] to draining-queue.
    8. If result is a normal completion, set result to NormalCompletion(undefined).
    9. If result is a return completion, set result to NormalCompletion(result.[[Value]]).
    10. Perform AsyncGeneratorCompleteStep(acGenerator, result, true).
    11. Perform AsyncGeneratorDrainQueue(acGenerator).
    12. Return undefined.
  5. Set the code evaluation state of genContext such that when evaluation is resumed for that execution context, closure will be called with no arguments.
  6. Set generator.[[AsyncGeneratorContext]] to genContext.
  7. Set generator.[[AsyncGeneratorQueue]] to a new empty List.
  8. Return unused.

27.6.3.3 AsyncGeneratorValidate ( generator, generatorBrand )

The abstract operation AsyncGeneratorValidate takes arguments generator (an ECMAScript language value) and generatorBrand (a String or empty) and returns either a normal completion containing unused or a throw completion. It performs the following steps when called:

  1. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorContext]]).
  2. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorState]]).
  3. Perform ? RequireInternalSlot(generator, [[AsyncGeneratorQueue]]).
  4. If generator.[[GeneratorBrand]] is not generatorBrand, throw a TypeError exception.
  5. Return unused.

27.6.3.4 AsyncGeneratorEnqueue ( generator, completion, promiseCapability )

The abstract operation AsyncGeneratorEnqueue takes arguments generator (an AsyncGenerator), completion (a Completion Record), and promiseCapability (a PromiseCapability Record) and returns unused. It performs the following steps when called:

  1. Let request be AsyncGeneratorRequest { [[Completion]]: completion, [[Capability]]: promiseCapability }.
  2. Append request to generator.[[AsyncGeneratorQueue]].
  3. Return unused.

27.6.3.5 AsyncGeneratorCompleteStep ( generator, completion, done [ , realm ] )

The abstract operation AsyncGeneratorCompleteStep takes arguments generator (an AsyncGenerator), completion (a Completion Record), and done (a Boolean) and optional argument realm (a Realm Record) and returns unused. It performs the following steps when called:

  1. Assert: generator.[[AsyncGeneratorQueue]] is not empty.
  2. Let next be the first element of generator.[[AsyncGeneratorQueue]].
  3. Remove the first element from generator.[[AsyncGeneratorQueue]].
  4. Let promiseCapability be next.[[Capability]].
  5. Let value be completion.[[Value]].
  6. If completion is a throw completion, then
    1. Perform ! Call(promiseCapability.[[Reject]], undefined, « value »).
  7. Else,
    1. Assert: completion is a normal completion.
    2. If realm is present, then
      1. Let oldRealm be the running execution context's Realm.
      2. Set the running execution context's Realm to realm.
      3. Let iteratorResult be CreateIteratorResultObject(value, done).
      4. Set the running execution context's Realm to oldRealm.
    3. Else,
      1. Let iteratorResult be CreateIteratorResultObject(value, done).
    4. Perform ! Call(promiseCapability.[[Resolve]], undefined, « iteratorResult »).
  8. Return unused.

27.6.3.6 AsyncGeneratorResume ( generator, completion )

The abstract operation AsyncGeneratorResume takes arguments generator (an AsyncGenerator) and completion (a Completion Record) and returns unused. It performs the following steps when called:

  1. Assert: generator.[[AsyncGeneratorState]] is either suspended-start or suspended-yield.
  2. Let genContext be generator.[[AsyncGeneratorContext]].
  3. Let callerContext be the running execution context.
  4. Suspend callerContext.
  5. Set generator.[[AsyncGeneratorState]] to executing.
  6. Push genContext onto the execution context stack; genContext is now the running execution context.
  7. Resume the suspended evaluation of genContext using completion as the result of the operation that suspended it. Let result be the Completion Record returned by the resumed computation.
  8. Assert: result is never an abrupt completion.
  9. Assert: When we return here, genContext has already been removed from the execution context stack and callerContext is the currently running execution context.
  10. Return unused.

27.6.3.7 AsyncGeneratorUnwrapYieldResumption ( resumptionValue )

The abstract operation AsyncGeneratorUnwrapYieldResumption takes argument resumptionValue (a Completion Record) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. If resumptionValue is not a return completion, return ? resumptionValue.
  2. Let awaited be Completion(Await(resumptionValue.[[Value]])).
  3. If awaited is a throw completion, return ? awaited.
  4. Assert: awaited is a normal completion.
  5. Return ReturnCompletion(awaited.[[Value]]).

27.6.3.8 AsyncGeneratorYield ( value )

The abstract operation AsyncGeneratorYield takes argument value (an ECMAScript language value) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:

  1. Let genContext be the running execution context.
  2. Assert: genContext is the execution context of a generator.
  3. Let generator be the value of the Generator component of genContext.
  4. Assert: GetGeneratorKind() is async.
  5. Let completion be NormalCompletion(value).
  6. Assert: The execution context stack has at least two elements.
  7. Let previousContext be the second to top element of the execution context stack.
  8. Let previousRealm be previousContext's Realm.
  9. Perform AsyncGeneratorCompleteStep(generator, completion, false, previousRealm).
  10. Let queue be generator.[[AsyncGeneratorQueue]].
  11. If queue is not empty, then
    1. NOTE: Execution continues without suspending the generator.
    2. Let toYield be the first element of queue.
    3. Let resumptionValue be Completion(toYield.[[Completion]]).
    4. Return ? AsyncGeneratorUnwrapYieldResumption(resumptionValue).
  12. Else,
    1. Set generator.[[AsyncGeneratorState]] to suspended-yield.
    2. Remove genContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
    3. Let callerContext be the running execution context.
    4. Resume callerContext passing undefined. If genContext is ever resumed again, let resumptionValue be the Completion Record with which it is resumed.
    5. Assert: If control reaches here, then genContext is the running execution context again.
    6. Return ? AsyncGeneratorUnwrapYieldResumption(resumptionValue).

27.6.3.9 AsyncGeneratorAwaitReturn ( generator )

The abstract operation AsyncGeneratorAwaitReturn takes argument generator (an AsyncGenerator) and returns unused. It performs the following steps when called:

  1. Assert: generator.[[AsyncGeneratorState]] is draining-queue.
  2. Let queue be generator.[[AsyncGeneratorQueue]].
  3. Assert: queue is not empty.
  4. Let next be the first element of queue.
  5. Let completion be Completion(next.[[Completion]]).
  6. Assert: completion is a return completion.
  7. Let promiseCompletion be Completion(PromiseResolve(%Promise%, completion.[[Value]])).
  8. If promiseCompletion is an abrupt completion, then
    1. Perform AsyncGeneratorCompleteStep(generator, promiseCompletion, true).
    2. Perform AsyncGeneratorDrainQueue(generator).
    3. Return unused.
  9. Assert: promiseCompletion is a normal completion.
  10. Let promise be promiseCompletion.[[Value]].
  11. Let fulfilledClosure be a new Abstract Closure with parameters (value) that captures generator and performs the following steps when called:
    1. Assert: generator.[[AsyncGeneratorState]] is draining-queue.
    2. Let result be NormalCompletion(value).
    3. Perform AsyncGeneratorCompleteStep(generator, result, true).
    4. Perform AsyncGeneratorDrainQueue(generator).
    5. Return undefined.
  12. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
  13. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures generator and performs the following steps when called:
    1. Assert: generator.[[AsyncGeneratorState]] is draining-queue.
    2. Let result be ThrowCompletion(reason).
    3. Perform AsyncGeneratorCompleteStep(generator, result, true).
    4. Perform AsyncGeneratorDrainQueue(generator).
    5. Return undefined.
  14. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  15. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
  16. Return unused.

27.6.3.10 AsyncGeneratorDrainQueue ( generator )

The abstract operation AsyncGeneratorDrainQueue takes argument generator (an AsyncGenerator) and returns unused. It drains the generator's AsyncGeneratorQueue until it encounters an AsyncGeneratorRequest which holds a return completion. It performs the following steps when called:

  1. Assert: generator.[[AsyncGeneratorState]] is draining-queue.
  2. Let queue be generator.[[AsyncGeneratorQueue]].
  3. Repeat, while queue is not empty,
    1. Let next be the first element of queue.
    2. Let completion be Completion(next.[[Completion]]).
    3. If completion is a return completion, then
      1. Perform AsyncGeneratorAwaitReturn(generator).
      2. Return unused.
    4. Else,
      1. If completion is a normal completion, then
        1. Set completion to NormalCompletion(undefined).
      2. Perform AsyncGeneratorCompleteStep(generator, completion, true).
  4. Set generator.[[AsyncGeneratorState]] to completed.
  5. Return unused.

27.6.3.11 CreateAsyncIteratorFromClosure ( closure, generatorBrand, generatorPrototype )

The abstract operation CreateAsyncIteratorFromClosure takes arguments closure (an Abstract Closure with no parameters), generatorBrand (a String or empty), and generatorPrototype (an Object) and returns an AsyncGenerator. It performs the following steps when called:

  1. NOTE: closure can contain uses of the Await operation and uses of the Yield operation to yield an IteratorResult object.
  2. Let internalSlotsList be « [[AsyncGeneratorState]], [[AsyncGeneratorContext]], [[AsyncGeneratorQueue]], [[GeneratorBrand]] ».
  3. Let generator be OrdinaryObjectCreate(generatorPrototype, internalSlotsList).
  4. Set generator.[[GeneratorBrand]] to generatorBrand.
  5. Set generator.[[AsyncGeneratorState]] to suspended-start.
  6. Let callerContext be the running execution context.
  7. Let calleeContext be a new execution context.
  8. Set the Function of calleeContext to null.
  9. Set the Realm of calleeContext to the current Realm Record.
  10. Set the ScriptOrModule of calleeContext to callerContext's ScriptOrModule.
  11. If callerContext is not already suspended, suspend callerContext.
  12. Push calleeContext onto the execution context stack; calleeContext is now the running execution context.
  13. Perform AsyncGeneratorStart(generator, closure).
  14. Remove calleeContext from the execution context stack and restore callerContext as the running execution context.
  15. Return generator.

27.7 AsyncFunction Objects

AsyncFunctions are functions that are usually created by evaluating AsyncFunctionDeclarations, AsyncFunctionExpressions, AsyncMethods, and AsyncArrowFunctions. They may also be created by calling the %AsyncFunction% intrinsic.

27.7.1 The AsyncFunction Constructor

The AsyncFunction constructor:

  • is %AsyncFunction%.
  • is a subclass of Function.
  • creates and initializes a new AsyncFunction when called as a function rather than as a constructor. Thus the function call AsyncFunction(…) is equivalent to the object creation expression new AsyncFunction(…) with the same arguments.
  • may be used as the value of an extends clause of a class definition. Subclass constructors that intend to inherit the specified AsyncFunction behaviour must include a super call to the AsyncFunction constructor to create and initialize a subclass instance with the internal slots necessary for built-in async function behaviour. All ECMAScript syntactic forms for defining async function objects create direct instances of AsyncFunction. There is no syntactic means to create instances of AsyncFunction subclasses.

27.7.1.1 AsyncFunction ( ...parameterArgs, bodyArg )

The last argument (if any) specifies the body (executable code) of an async function. Any preceding arguments specify formal parameters.

This function performs the following steps when called:

  1. Let C be the active function object.
  2. If bodyArg is not present, set bodyArg to the empty String.
  3. Return ? CreateDynamicFunction(C, NewTarget, async, parameterArgs, bodyArg).
Note
See NOTE for 20.2.1.1.

27.7.2 Properties of the AsyncFunction Constructor

The AsyncFunction constructor:

  • is a standard built-in function object that inherits from the Function constructor.
  • has a [[Prototype]] internal slot whose value is %Function%.
  • has a "length" property whose value is 1𝔽.
  • has a "name" property whose value is "AsyncFunction".
  • has the following properties:

27.7.2.1 AsyncFunction.prototype

The initial value of AsyncFunction.prototype is the AsyncFunction prototype object.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

27.7.3 Properties of the AsyncFunction Prototype Object

The AsyncFunction prototype object:

27.7.3.1 AsyncFunction.prototype.constructor

The initial value of AsyncFunction.prototype.constructor is %AsyncFunction%.

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.7.3.2 AsyncFunction.prototype [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "AsyncFunction".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

27.7.4 AsyncFunction Instances

Every AsyncFunction instance is an ECMAScript function object and has the internal slots listed in Table 30. The value of the [[IsClassConstructor]] internal slot for all such instances is false. AsyncFunction instances are not constructors and do not have a [[Construct]] internal method. AsyncFunction instances do not have a prototype property as they are not constructable.

Each AsyncFunction instance has the following own properties:

27.7.4.1 length

The specification for the "length" property of Function instances given in 20.2.4.1 also applies to AsyncFunction instances.

27.7.4.2 name

The specification for the "name" property of Function instances given in 20.2.4.2 also applies to AsyncFunction instances.

27.7.5 Async Functions Abstract Operations

27.7.5.1 AsyncFunctionStart ( promiseCapability, asyncFunctionBody )

The abstract operation AsyncFunctionStart takes arguments promiseCapability (a PromiseCapability Record) and asyncFunctionBody (a FunctionBody Parse Node, an ExpressionBody Parse Node, or an Abstract Closure with no parameters) and returns unused. It performs the following steps when called:

  1. Let runningContext be the running execution context.
  2. Let asyncContext be a copy of runningContext.
  3. NOTE: Copying the execution state is required for AsyncBlockStart to resume its execution. It is ill-defined to resume a currently executing context.
  4. Perform AsyncBlockStart(promiseCapability, asyncFunctionBody, asyncContext).
  5. Return unused.

27.7.5.2 AsyncBlockStart ( promiseCapability, asyncBody, asyncContext )

The abstract operation AsyncBlockStart takes arguments promiseCapability (a PromiseCapability Record), asyncBody (a Parse Node or an Abstract Closure with no parameters), and asyncContext (an execution context) and returns unused. It performs the following steps when called:

  1. Let runningContext be the running execution context.
  2. Let closure be a new Abstract Closure with no parameters that captures promiseCapability and asyncBody and performs the following steps when called:
    1. Let acAsyncContext be the running execution context.
    2. If asyncBody is a Parse Node, then
      1. Let result be Completion(Evaluation of asyncBody).
    3. Else,
      1. Assert: asyncBody is an Abstract Closure with no parameters.
      2. Let result be Completion(asyncBody()).
    4. Assert: If we return here, the async function either threw an exception or performed an implicit or explicit return; all awaiting is done.
    5. Remove acAsyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
    6. If result is a normal completion, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « undefined »).
    7. Else if result is a return completion, then
      1. Perform ! Call(promiseCapability.[[Resolve]], undefined, « result.[[Value]] »).
    8. Else,
      1. Assert: result is a throw completion.
      2. Perform ! Call(promiseCapability.[[Reject]], undefined, « result.[[Value]] »).
    9. Return unused.
  3. Set the code evaluation state of asyncContext such that when evaluation is resumed for that execution context, closure will be called with no arguments.
  4. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
  5. Resume the suspended evaluation of asyncContext. Let result be the value returned by the resumed computation.
  6. Assert: When we return here, asyncContext has already been removed from the execution context stack and runningContext is the currently running execution context.
  7. Assert: result is a normal completion with a value of unused. The possible sources of this value are Await or, if the async function doesn't await anything, step 2.i above.
  8. Return unused.

27.7.5.3 Await ( value )

The abstract operation Await takes argument value (an ECMAScript language value) and returns either a normal completion containing either an ECMAScript language value or empty, or a throw completion. It performs the following steps when called:

  1. Let asyncContext be the running execution context.
  2. Let promise be ? PromiseResolve(%Promise%, value).
  3. Let fulfilledClosure be a new Abstract Closure with parameters (v) that captures asyncContext and performs the following steps when called:
    1. Let prevContext be the running execution context.
    2. Suspend prevContext.
    3. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
    4. Resume the suspended evaluation of asyncContext using NormalCompletion(v) as the result of the operation that suspended it.
    5. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
    6. Return undefined.
  4. Let onFulfilled be CreateBuiltinFunction(fulfilledClosure, 1, "", « »).
  5. Let rejectedClosure be a new Abstract Closure with parameters (reason) that captures asyncContext and performs the following steps when called:
    1. Let prevContext be the running execution context.
    2. Suspend prevContext.
    3. Push asyncContext onto the execution context stack; asyncContext is now the running execution context.
    4. Resume the suspended evaluation of asyncContext using ThrowCompletion(reason) as the result of the operation that suspended it.
    5. Assert: When we reach this step, asyncContext has already been removed from the execution context stack and prevContext is the currently running execution context.
    6. Return undefined.
  6. Let onRejected be CreateBuiltinFunction(rejectedClosure, 1, "", « »).
  7. Perform PerformPromiseThen(promise, onFulfilled, onRejected).
  8. Remove asyncContext from the execution context stack and restore the execution context that is at the top of the execution context stack as the running execution context.
  9. Let callerContext be the running execution context.
  10. Resume callerContext passing empty. If asyncContext is ever resumed again, let completion be the Completion Record with which it is resumed.
  11. Assert: If control reaches here, then asyncContext is the running execution context again.
  12. Return completion.

28 Reflection

28.1 The Reflect Object

The Reflect object:

  • is %Reflect%.
  • is the initial value of the "Reflect" property of the global object.
  • is an ordinary object.
  • has a [[Prototype]] internal slot whose value is %Object.prototype%.
  • is not a function object.
  • does not have a [[Construct]] internal method; it cannot be used as a constructor with the new operator.
  • does not have a [[Call]] internal method; it cannot be invoked as a function.

28.1.1 Reflect.apply ( target, thisArgument, argumentsList )

This function performs the following steps when called:

  1. If IsCallable(target) is false, throw a TypeError exception.
  2. Let args be ? CreateListFromArrayLike(argumentsList).
  3. Perform PrepareForTailCall().
  4. Return ? Call(target, thisArgument, args).

28.1.2 Reflect.construct ( target, argumentsList [ , newTarget ] )

This function performs the following steps when called:

  1. If IsConstructor(target) is false, throw a TypeError exception.
  2. If newTarget is not present, set newTarget to target.
  3. Else if IsConstructor(newTarget) is false, throw a TypeError exception.
  4. Let args be ? CreateListFromArrayLike(argumentsList).
  5. Return ? Construct(target, args, newTarget).

28.1.3 Reflect.defineProperty ( target, propertyKey, attributes )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. Let desc be ? ToPropertyDescriptor(attributes).
  4. Return ? target.[[DefineOwnProperty]](key, desc).

28.1.4 Reflect.deleteProperty ( target, propertyKey )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. Return ? target.[[Delete]](key).

28.1.5 Reflect.get ( target, propertyKey [ , receiver ] )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. If receiver is not present, then
    1. Set receiver to target.
  4. Return ? target.[[Get]](key, receiver).

28.1.6 Reflect.getOwnPropertyDescriptor ( target, propertyKey )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. Let desc be ? target.[[GetOwnProperty]](key).
  4. Return FromPropertyDescriptor(desc).

28.1.7 Reflect.getPrototypeOf ( target )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Return ? target.[[GetPrototypeOf]]().

28.1.8 Reflect.has ( target, propertyKey )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. Return ? target.[[HasProperty]](key).

28.1.9 Reflect.isExtensible ( target )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Return ? target.[[IsExtensible]]().

28.1.10 Reflect.ownKeys ( target )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let keys be ? target.[[OwnPropertyKeys]]().
  3. Return CreateArrayFromList(keys).

28.1.11 Reflect.preventExtensions ( target )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Return ? target.[[PreventExtensions]]().

28.1.12 Reflect.set ( target, propertyKey, V [ , receiver ] )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. Let key be ? ToPropertyKey(propertyKey).
  3. If receiver is not present, then
    1. Set receiver to target.
  4. Return ? target.[[Set]](key, V, receiver).

28.1.13 Reflect.setPrototypeOf ( target, proto )

This function performs the following steps when called:

  1. If target is not an Object, throw a TypeError exception.
  2. If proto is not an Object and proto is not null, throw a TypeError exception.
  3. Return ? target.[[SetPrototypeOf]](proto).

28.1.14 Reflect [ %Symbol.toStringTag% ]

The initial value of the %Symbol.toStringTag% property is the String value "Reflect".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: true }.

28.2 Proxy Objects

28.2.1 The Proxy Constructor

The Proxy constructor:

  • is %Proxy%.
  • is the initial value of the "Proxy" property of the global object.
  • creates and initializes a new Proxy object when called as a constructor.
  • is not intended to be called as a function and will throw an exception when called in that manner.

28.2.1.1 Proxy ( target, handler )

This function performs the following steps when called:

  1. If NewTarget is undefined, throw a TypeError exception.
  2. Return ? ProxyCreate(target, handler).

28.2.2 Properties of the Proxy Constructor

The Proxy constructor:

  • has a [[Prototype]] internal slot whose value is %Function.prototype%.
  • does not have a "prototype" property because Proxy objects do not have a [[Prototype]] internal slot that requires initialization.
  • has the following properties:

28.2.2.1 Proxy.revocable ( target, handler )

This function creates a revocable Proxy object.

It performs the following steps when called:

  1. Let proxy be ? ProxyCreate(target, handler).
  2. Let revokerClosure be a new Abstract Closure with no parameters that captures nothing and performs the following steps when called:
    1. Let F be the active function object.
    2. Let p be F.[[RevocableProxy]].
    3. If p is null, return undefined.
    4. Set F.[[RevocableProxy]] to null.
    5. Assert: p is a Proxy exotic object.
    6. Set p.[[ProxyTarget]] to null.
    7. Set p.[[ProxyHandler]] to null.
    8. Return undefined.
  3. Let revoker be CreateBuiltinFunction(revokerClosure, 0, "", « [[RevocableProxy]] »).
  4. Set revoker.[[RevocableProxy]] to proxy.
  5. Let result be OrdinaryObjectCreate(%Object.prototype%).
  6. Perform ! CreateDataPropertyOrThrow(result, "proxy", proxy).
  7. Perform ! CreateDataPropertyOrThrow(result, "revoke", revoker).
  8. Return result.

28.3 Module Namespace Objects

A Module Namespace Object is a module namespace exotic object that provides runtime property-based access to a module's exported bindings. There is no constructor function for Module Namespace Objects. Instead, such an object is created for each module that is imported by an ImportDeclaration that contains a NameSpaceImport.

In addition to the properties specified in 10.4.6 each Module Namespace Object has the following own property:

28.3.1 %Symbol.toStringTag%

The initial value of the %Symbol.toStringTag% property is the String value "Module".

This property has the attributes { [[Writable]]: false, [[Enumerable]]: false, [[Configurable]]: false }.

29 Memory Model

The memory consistency model, or memory model, specifies the possible orderings of Shared Data Block events, arising via accessing TypedArray instances backed by a SharedArrayBuffer and via methods on the Atomics object. When the program has no data races (defined below), the ordering of events appears as sequentially consistent, i.e., as an interleaving of actions from each agent. When the program has data races, shared memory operations may appear sequentially inconsistent. For example, programs may exhibit causality-violating behaviour and other astonishments. These astonishments arise from compiler transforms and the design of CPUs (e.g., out-of-order execution and speculation). The memory model defines both the precise conditions under which a program exhibits sequentially consistent behaviour as well as the possible values read from data races. To wit, there is no undefined behaviour.

The memory model is defined as relational constraints on events introduced by abstract operations on SharedArrayBuffer or by methods on the Atomics object during an evaluation.

Note

This section provides an axiomatic model on events introduced by the abstract operations on SharedArrayBuffers. It bears stressing that the model is not expressible algorithmically, unlike the rest of this specification. The nondeterministic introduction of events by abstract operations is the interface between the operational semantics of ECMAScript evaluation and the axiomatic semantics of the memory model. The semantics of these events is defined by considering graphs of all events in an evaluation. These are neither Static Semantics nor Runtime Semantics. There is no demonstrated algorithmic implementation, but instead a set of constraints that determine if a particular event graph is allowed or disallowed.

29.1 Memory Model Fundamentals

Shared memory accesses (reads and writes) are divided into two groups, atomic accesses and data accesses, defined below. Atomic accesses are sequentially consistent, i.e., there is a strict total ordering of events agreed upon by all agents in an agent cluster. Non-atomic accesses do not have a strict total ordering agreed upon by all agents, i.e., unordered.

Note 1

No orderings weaker than sequentially consistent and stronger than unordered, such as release-acquire, are supported.

A Shared Data Block event is either a ReadSharedMemory, WriteSharedMemory, or ReadModifyWriteSharedMemory Record.

Table 96: ReadSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst or unordered The weakest ordering guaranteed by the memory model for the event.
[[NoTear]] a Boolean Whether this event is allowed to read from multiple write events with equal range as this event.
[[Block]] a Shared Data Block The block the event operates on.
[[ByteIndex]] a non-negative integer The byte address of the read in [[Block]].
[[ElementSize]] a non-negative integer The size of the read.
Table 97: WriteSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst, unordered, or init The weakest ordering guaranteed by the memory model for the event.
[[NoTear]] a Boolean Whether this event is allowed to be read from multiple read events with equal range as this event.
[[Block]] a Shared Data Block The block the event operates on.
[[ByteIndex]] a non-negative integer The byte address of the write in [[Block]].
[[ElementSize]] a non-negative integer The size of the write.
[[Payload]] a List of byte values The List of byte values to be read by other events.
Table 98: ReadModifyWriteSharedMemory Event Fields
Field Name Value Meaning
[[Order]] seq-cst Read-modify-write events are always sequentially consistent.
[[NoTear]] true Read-modify-write events cannot tear.
[[Block]] a Shared Data Block The block the event operates on.
[[ByteIndex]] a non-negative integer The byte address of the read-modify-write in [[Block]].
[[ElementSize]] a non-negative integer The size of the read-modify-write.
[[Payload]] a List of byte values The List of byte values to be passed to [[ModifyOp]].
[[ModifyOp]] a read-modify-write modification function An abstract closure that returns a modified List of byte values from a read List of byte values and [[Payload]].

These events are introduced by abstract operations or by methods on the Atomics object.

Some operations may also introduce Synchronize events. A Synchronize event has no fields, and exists purely to directly constrain the permitted orderings of other events.

In addition to Shared Data Block and Synchronize events, there are host-specific events.

Let the range of a ReadSharedMemory, WriteSharedMemory, or ReadModifyWriteSharedMemory event be the Set of contiguous integers from its [[ByteIndex]] to [[ByteIndex]] + [[ElementSize]] - 1. Two events' ranges are equal when the events have the same [[Block]], and the ranges are element-wise equal. Two events' ranges are overlapping when the events have the same [[Block]], the ranges are not equal and their intersection is non-empty. Two events' ranges are disjoint when the events do not have the same [[Block]] or their ranges are neither equal nor overlapping.

Note 2

Examples of host-specific synchronizing events that should be accounted for are: sending a SharedArrayBuffer from one agent to another (e.g., by postMessage in a browser), starting and stopping agents, and communicating within the agent cluster via channels other than shared memory. For a particular execution execution, those events are provided by the host via the host-synchronizes-with strict partial order. Additionally, hosts can add host-specific synchronizing events to execution.[[EventList]] so as to participate in the is-agent-order-before Relation.

Events are ordered within candidate executions by the relations defined below.

29.2 Agent Events Records

An Agent Events Record is a Record with the following fields.

Table 99: Agent Events Record Fields
Field Name Value Meaning
[[AgentSignifier]] an agent signifier The agent whose evaluation resulted in this ordering.
[[EventList]] a List of events Events are appended to the list during evaluation.
[[AgentSynchronizesWith]] a List of pairs of Synchronize events Synchronize relationships introduced by the operational semantics.

29.3 Chosen Value Records

A Chosen Value Record is a Record with the following fields.

Table 100: Chosen Value Record Fields
Field Name Value Meaning
[[Event]] a Shared Data Block event The ReadSharedMemory or ReadModifyWriteSharedMemory event that was introduced for this chosen value.
[[ChosenValue]] a List of byte values The bytes that were nondeterministically chosen during evaluation.

29.4 Candidate Executions

A candidate execution of the evaluation of an agent cluster is a Record with the following fields.

Table 101: Candidate Execution Record Fields
Field Name Value Meaning
[[EventsRecords]] a List of Agent Events Records Maps an agent to Lists of events appended during the evaluation.
[[ChosenValues]] a List of Chosen Value Records Maps ReadSharedMemory or ReadModifyWriteSharedMemory events to the List of byte values chosen during the evaluation.

An empty candidate execution is a candidate execution Record whose fields are empty Lists.

29.5 Abstract Operations for the Memory Model

29.5.1 EventSet ( execution )

The abstract operation EventSet takes argument execution (a candidate execution) and returns a Set of events. It performs the following steps when called:

  1. Let events be an empty Set.
  2. For each Agent Events Record aer of execution.[[EventsRecords]], do
    1. For each event E of aer.[[EventList]], do
      1. Add E to events.
  3. Return events.

29.5.2 SharedDataBlockEventSet ( execution )

The abstract operation SharedDataBlockEventSet takes argument execution (a candidate execution) and returns a Set of events. It performs the following steps when called:

  1. Let events be an empty Set.
  2. For each event E of EventSet(execution), do
    1. If E is a ReadSharedMemory, WriteSharedMemory, or ReadModifyWriteSharedMemory event, add E to events.
  3. Return events.

29.5.3 HostEventSet ( execution )

The abstract operation HostEventSet takes argument execution (a candidate execution) and returns a Set of events. It performs the following steps when called:

  1. Let events be an empty Set.
  2. For each event E of EventSet(execution), do
    1. If E is not in SharedDataBlockEventSet(execution), add E to events.
  3. Return events.

29.5.4 ComposeWriteEventBytes ( execution, byteIndex, Ws )

The abstract operation ComposeWriteEventBytes takes arguments execution (a candidate execution), byteIndex (a non-negative integer), and Ws (a List of either WriteSharedMemory or ReadModifyWriteSharedMemory events) and returns a List of byte values. It performs the following steps when called:

  1. Let byteLocation be byteIndex.
  2. Let bytesRead be a new empty List.
  3. For each element W of Ws, do
    1. Assert: W has byteLocation in its range.
    2. Let payloadIndex be byteLocation - W.[[ByteIndex]].
    3. If W is a WriteSharedMemory event, then
      1. Let byte be W.[[Payload]][payloadIndex].
    4. Else,
      1. Assert: W is a ReadModifyWriteSharedMemory event.
      2. Let bytes be ValueOfReadEvent(execution, W).
      3. Let bytesModified be W.[[ModifyOp]](bytes, W.[[Payload]]).
      4. Let byte be bytesModified[payloadIndex].
    5. Append byte to bytesRead.
    6. Set byteLocation to byteLocation + 1.
  4. Return bytesRead.
Note 1

The read-modify-write modification [[ModifyOp]] is given by the function properties on the Atomics object that introduce ReadModifyWriteSharedMemory events.

Note 2

This abstract operation composes a List of write events into a List of byte values. It is used in the event semantics of ReadSharedMemory and ReadModifyWriteSharedMemory events.

29.5.5 ValueOfReadEvent ( execution, R )

The abstract operation ValueOfReadEvent takes arguments execution (a candidate execution) and R (a ReadSharedMemory or ReadModifyWriteSharedMemory event) and returns a List of byte values. It performs the following steps when called:

  1. Let Ws be reads-bytes-from(R) in execution.
  2. Assert: Ws is a List of WriteSharedMemory or ReadModifyWriteSharedMemory events with length equal to R.[[ElementSize]].
  3. Return ComposeWriteEventBytes(execution, R.[[ByteIndex]], Ws).

29.6 Relations of Candidate Executions

The following relations and mathematical functions are parameterized over a particular candidate execution and order its events.

29.6.1 is-agent-order-before

For a candidate execution execution, its is-agent-order-before Relation is the least Relation on events that satisfies the following.

  • For events E and D, E is-agent-order-before D in execution if there is some Agent Events Record aer in execution.[[EventsRecords]] such that aer.[[EventList]] contains both E and D and E is before D in List order of aer.[[EventList]].
Note

Each agent introduces events in a per-agent strict total order during the evaluation. This is the union of those strict total orders.

29.6.2 reads-bytes-from

For a candidate execution execution, its reads-bytes-from function is a mathematical function mapping events in SharedDataBlockEventSet(execution) to Lists of events in SharedDataBlockEventSet(execution) that satisfies the following conditions.

A candidate execution always admits a reads-bytes-from function.

29.6.3 reads-from

For a candidate execution execution, its reads-from Relation is the least Relation on events that satisfies the following.

29.6.4 host-synchronizes-with

For a candidate execution execution, its host-synchronizes-with Relation is a host-provided strict partial order on host-specific events that satisfies at least the following.

  • If E host-synchronizes-with D in execution, HostEventSet(execution) contains E and D.
  • There is no cycle in the union of host-synchronizes-with and is-agent-order-before in execution.
Note 1

For two host-specific events E and D in a candidate execution execution, E host-synchronizes-with D in execution implies E happens-before D in execution.

Note 2

This Relation allows the host to provide additional synchronization mechanisms, such as postMessage between HTML workers.

29.6.5 synchronizes-with

For a candidate execution execution, its synchronizes-with Relation is the least Relation on events that satisfies the following.

  • For events R and W, W synchronizes-with R in execution if R reads-from W in execution, R.[[Order]] is seq-cst, W.[[Order]] is seq-cst, and R and W have equal ranges.
  • For each element eventsRecord of execution.[[EventsRecords]], the following is true.
    • For events S and Sw, S synchronizes-with Sw in execution if eventsRecord.[[AgentSynchronizesWith]] contains (S, Sw).
  • For events E and D, E synchronizes-with D in execution if execution.[[HostSynchronizesWith]] contains (E, D).
Note 1

Owing to convention in memory model literature, in a candidate execution execution, write events synchronizes-with read events, instead of read events synchronizes-with write events.

Note 2

In a candidate execution execution, init events do not participate in this Relation and are instead constrained directly by happens-before.

Note 3

In a candidate execution execution, not all seq-cst events related by reads-from are related by synchronizes-with. Only events that also have equal ranges are related by synchronizes-with.

Note 4

For Shared Data Block events R and W in a candidate execution execution such that W synchronizes-with R, R may reads-from other writes than W.

29.6.6 happens-before

For a candidate execution execution, its happens-before Relation is the least Relation on events that satisfies the following.

  • For events E and D, E happens-before D in execution if any of the following conditions are true.

Note

Because happens-before is a superset of agent-order, a candidate execution is consistent with the single-thread evaluation semantics of ECMAScript.

29.7 Properties of Valid Executions

29.7.1 Valid Chosen Reads

A candidate execution execution has valid chosen reads if the following algorithm returns true.

  1. For each ReadSharedMemory or ReadModifyWriteSharedMemory event R of SharedDataBlockEventSet(execution), do
    1. Let chosenValueRecord be the element of execution.[[ChosenValues]] whose [[Event]] field is R.
    2. Let chosenValue be chosenValueRecord.[[ChosenValue]].
    3. Let readValue be ValueOfReadEvent(execution, R).
    4. Let chosenLen be the number of elements in chosenValue.
    5. Let readLen be the number of elements in readValue.
    6. If chosenLenreadLen, then
      1. Return false.
    7. If chosenValue[i] ≠ readValue[i] for some integer i in the interval from 0 (inclusive) to chosenLen (exclusive), then
      1. Return false.
  2. Return true.

29.7.2 Coherent Reads

A candidate execution execution has coherent reads if the following algorithm returns true.

  1. For each ReadSharedMemory or ReadModifyWriteSharedMemory event R of SharedDataBlockEventSet(execution), do
    1. Let Ws be reads-bytes-from(R) in execution.
    2. Let byteLocation be R.[[ByteIndex]].
    3. For each element W of Ws, do
      1. If R happens-before W in execution, then
        1. Return false.
      2. If there exists a WriteSharedMemory or ReadModifyWriteSharedMemory event V that has byteLocation in its range such that W happens-before V in execution and V happens-before R in execution, then
        1. Return false.
      3. Set byteLocation to byteLocation + 1.
  2. Return true.

29.7.3 Tear Free Reads

A candidate execution execution has tear free reads if the following algorithm returns true.

  1. For each ReadSharedMemory or ReadModifyWriteSharedMemory event R of SharedDataBlockEventSet(execution), do
    1. If R.[[NoTear]] is true, then
      1. Assert: The remainder of dividing R.[[ByteIndex]] by R.[[ElementSize]] is 0.
      2. For each event W such that R reads-from W in execution and W.[[NoTear]] is true, do
        1. If R and W have equal ranges and there exists an event V such that V and W have equal ranges, V.[[NoTear]] is true, W and V are not the same Shared Data Block event, and R reads-from V in execution, then
          1. Return false.
  2. Return true.
Note

An event's [[NoTear]] field is true when that event was introduced via accessing an integer TypedArray, and false when introduced via accessing a floating point TypedArray or DataView.

Intuitively, this requirement says when a memory range is accessed in an aligned fashion via an integer TypedArray, a single write event on that range must "win" when in a data race with other write events with equal ranges. More precisely, this requirement says an aligned read event cannot read a value composed of bytes from multiple, different write events all with equal ranges. It is possible, however, for an aligned read event to read from multiple write events with overlapping ranges.

29.7.4 Sequentially Consistent Atomics

For a candidate execution execution, is-memory-order-before is a strict total order of all events in EventSet(execution) that satisfies the following.

A candidate execution has sequentially consistent atomics if it admits an is-memory-order-before Relation.

Note 3

While is-memory-order-before includes all events in EventSet(execution), those that are not constrained by happens-before or synchronizes-with in execution are allowed to occur anywhere in the order.

29.7.5 Valid Executions

A candidate execution execution is a valid execution (or simply an execution) if all of the following are true.

All programs have at least one valid execution.

29.8 Races

For an execution execution and events E and D that are contained in SharedDataBlockEventSet(execution), E and D are in a race if the following algorithm returns true.

  1. If E and D are not the same Shared Data Block event, then
    1. If it is not the case that both E happens-before D in execution and D happens-before E in execution, then
      1. If E and D are both WriteSharedMemory or ReadModifyWriteSharedMemory events and E and D do not have disjoint ranges, then
        1. Return true.
      2. If E reads-from D in execution or D reads-from E in execution, then
        1. Return true.
  2. Return false.

29.9 Data Races

For an execution execution and events E and D that are contained in SharedDataBlockEventSet(execution), E and D are in a data race if the following algorithm returns true.

  1. If E and D are in a race in execution, then
    1. If E.[[Order]] is not seq-cst or D.[[Order]] is not seq-cst, then
      1. Return true.
    2. If E and D have overlapping ranges, then
      1. Return true.
  2. Return false.

29.10 Data Race Freedom

An execution execution is data race free if there are no two events in SharedDataBlockEventSet(execution) that are in a data race.

A program is data race free if all its executions are data race free.

The memory model guarantees sequential consistency of all events for data race free programs.

29.11 Shared Memory Guidelines

Note 1

The following are guidelines for ECMAScript programmers working with shared memory.

We recommend programs be kept data race free, i.e., make it so that it is impossible for there to be concurrent non-atomic operations on the same memory location. Data race free programs have interleaving semantics where each step in the evaluation semantics of each agent are interleaved with each other. For data race free programs, it is not necessary to understand the details of the memory model. The details are unlikely to build intuition that will help one to better write ECMAScript.

More generally, even if a program is not data race free it may have predictable behaviour, so long as atomic operations are not involved in any data races and the operations that race all have the same access size. The simplest way to arrange for atomics not to be involved in races is to ensure that different memory cells are used by atomic and non-atomic operations and that atomic accesses of different sizes are not used to access the same cells at the same time. Effectively, the program should treat shared memory as strongly typed as much as possible. One still cannot depend on the ordering and timing of non-atomic accesses that race, but if memory is treated as strongly typed the racing accesses will not "tear" (bits of their values will not be mixed).

Note 2

The following are guidelines for ECMAScript implementers writing compiler transformations for programs using shared memory.

It is desirable to allow most program transformations that are valid in a single-agent setting in a multi-agent setting, to ensure that the performance of each agent in a multi-agent program is as good as it would be in a single-agent setting. Frequently these transformations are hard to judge. We outline some rules about program transformations that are intended to be taken as normative (in that they are implied by the memory model or stronger than what the memory model implies) but which are likely not exhaustive. These rules are intended to apply to program transformations that precede the introductions of the events that make up the is-agent-order-before Relation.

Let an agent-order slice be the subset of the is-agent-order-before Relation pertaining to a single agent.

Let possible read values of a read event be the set of all values of ValueOfReadEvent for that event across all valid executions.

Any transformation of an agent-order slice that is valid in the absence of shared memory is valid in the presence of shared memory, with the following exceptions.

  • Atomics are carved in stone: Program transformations must not cause the seq-cst events in an agent-order slice to be reordered with its unordered operations, nor its seq-cst operations to be reordered with each other, nor may a program transformation remove a seq-cst operation from the is-agent-order-before Relation.

    (In practice, the prohibition on reorderings forces a compiler to assume that every seq-cst operation is a synchronization and included in the final is-memory-order-before Relation, which it would usually have to assume anyway in the absence of inter-agent program analysis. It also forces the compiler to assume that every call where the callee's effects on the memory-order are unknown may contain seq-cst operations.)

  • Reads must be stable: Any given shared memory read must only observe a single value in an execution.

    (For example, if what is semantically a single read in the program is executed multiple times then the program is subsequently allowed to observe only one of the values read. A transformation known as rematerialization can violate this rule.)

  • Writes must be stable: All observable writes to shared memory must follow from program semantics in an execution.

    (For example, a transformation may not introduce certain observable writes, such as by using read-modify-write operations on a larger location to write a smaller datum, writing a value to memory that the program could not have written, or writing a just-read value back to the location it was read from, if that location could have been overwritten by another agent after the read.)

  • Possible read values must be non-empty: Program transformations cannot cause the possible read values of a shared memory read to become empty.

    (Counterintuitively, this rule in effect restricts transformations on writes, because writes have force in memory model insofar as to be read by read events. For example, writes may be moved and coalesced and sometimes reordered between two seq-cst operations, but the transformation may not remove every write that updates a location; some write must be preserved.)

Examples of transformations that remain valid are: merging multiple non-atomic reads from the same location, reordering non-atomic reads, introducing speculative non-atomic reads, merging multiple non-atomic writes to the same location, reordering non-atomic writes to different locations, and hoisting non-atomic reads out of loops even if that affects termination. Note in general that aliased TypedArrays make it hard to prove that locations are different.

Note 3

The following are guidelines for ECMAScript implementers generating machine code for shared memory accesses.

For architectures with memory models no weaker than those of ARM or Power, non-atomic stores and loads may be compiled to bare stores and loads on the target architecture. Atomic stores and loads may be compiled down to instructions that guarantee sequential consistency. If no such instructions exist, memory barriers are to be employed, such as placing barriers on both sides of a bare store or load. Read-modify-write operations may be compiled to read-modify-write instructions on the target architecture, such as LOCK-prefixed instructions on x86, load-exclusive/store-exclusive instructions on ARM, and load-link/store-conditional instructions on Power.

Specifically, the memory model is intended to allow code generation as follows.

  • Every atomic operation in the program is assumed to be necessary.
  • Atomic operations are never rearranged with each other or with non-atomic operations.
  • Functions are always assumed to perform atomic operations.
  • Atomic operations are never implemented as read-modify-write operations on larger data, but as non-lock-free atomics if the platform does not have atomic operations of the appropriate size. (We already assume that every platform has normal memory access operations of every interesting size.)

Naive code generation uses these patterns:

  • Regular loads and stores compile to single load and store instructions.
  • Lock-free atomic loads and stores compile to a full (sequentially consistent) fence, a regular load or store, and a full fence.
  • Lock-free atomic read-modify-write accesses compile to a full fence, an atomic read-modify-write instruction sequence, and a full fence.
  • Non-lock-free atomics compile to a spinlock acquire, a full fence, a series of non-atomic load and store instructions, a full fence, and a spinlock release.

That mapping is correct so long as an atomic operation on an address range does not race with a non-atomic write or with an atomic operation of different size. However, that is all we need: the memory model effectively demotes the atomic operations involved in a race to non-atomic status. On the other hand, the naive mapping is quite strong: it allows atomic operations to be used as sequentially consistent fences, which the memory model does not actually guarantee.

Local improvements to those basic patterns are also allowed, subject to the constraints of the memory model. For example:

  • There are obvious platform-dependent improvements that remove redundant fences. For example, on x86 the fences around lock-free atomic loads and stores can always be omitted except for the fence following a store, and no fence is needed for lock-free read-modify-write instructions, as these all use LOCK-prefixed instructions. On many platforms there are fences of several strengths, and weaker fences can be used in certain contexts without destroying sequential consistency.
  • Most modern platforms support lock-free atomics for all the data sizes required by ECMAScript atomics. Should non-lock-free atomics be needed, the fences surrounding the body of the atomic operation can usually be folded into the lock and unlock steps. The simplest solution for non-lock-free atomics is to have a single lock word per SharedArrayBuffer.
  • There are also more complicated platform-dependent local improvements, requiring some code analysis. For example, two back-to-back fences often have the same effect as a single fence, so if code is generated for two atomic operations in sequence, only a single fence need separate them. On x86, even a single fence separating atomic stores can be omitted, as the fence following a store is only needed to separate the store from a subsequent load.

Annex A (informative) Grammar Summary

A.1 Lexical Grammar

SourceCharacter :: any Unicode code point InputElementDiv :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator RightBracePunctuator InputElementRegExp :: WhiteSpace LineTerminator Comment CommonToken RightBracePunctuator RegularExpressionLiteral InputElementRegExpOrTemplateTail :: WhiteSpace LineTerminator Comment CommonToken RegularExpressionLiteral TemplateSubstitutionTail InputElementTemplateTail :: WhiteSpace LineTerminator Comment CommonToken DivPunctuator TemplateSubstitutionTail InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral WhiteSpace :: <TAB> <VT> <FF> <ZWNBSP> <USP> LineTerminator :: <LF> <CR> <LS> <PS> LineTerminatorSequence :: <LF> <CR> [lookahead ≠ <LF>] <LS> <PS> <CR> <LF> Comment :: MultiLineComment SingleLineComment MultiLineComment :: /* MultiLineCommentCharsopt */ MultiLineCommentChars :: MultiLineNotAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt PostAsteriskCommentChars :: MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentCharsopt * PostAsteriskCommentCharsopt MultiLineNotAsteriskChar :: SourceCharacter but not * MultiLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * SingleLineComment :: // SingleLineCommentCharsopt SingleLineCommentChars :: SingleLineCommentChar SingleLineCommentCharsopt SingleLineCommentChar :: SourceCharacter but not LineTerminator HashbangComment :: #! SingleLineCommentCharsopt CommonToken :: IdentifierName PrivateIdentifier Punctuator NumericLiteral StringLiteral Template PrivateIdentifier :: # IdentifierName IdentifierName :: IdentifierStart IdentifierName IdentifierPart IdentifierStart :: IdentifierStartChar \ UnicodeEscapeSequence IdentifierPart :: IdentifierPartChar \ UnicodeEscapeSequence IdentifierStartChar :: UnicodeIDStart $ _ IdentifierPartChar :: UnicodeIDContinue $ AsciiLetter :: one of a b c d e f g h i j k l m n o p q r s t u v w x y z A B C D E F G H I J K L M N O P Q R S T U V W X Y Z UnicodeIDStart :: any Unicode code point with the Unicode property “ID_Start” UnicodeIDContinue :: any Unicode code point with the Unicode property “ID_Continue” ReservedWord :: one of await break case catch class const continue debugger default delete do else enum export extends false finally for function if import in instanceof new null return super switch this throw true try typeof var void while with yield Punctuator :: OptionalChainingPunctuator OtherPunctuator OptionalChainingPunctuator :: ?. [lookahead ∉ DecimalDigit] OtherPunctuator :: one of { ( ) [ ] . ... ; , < > <= >= == != === !== + - * % ** ++ -- << >> >>> & | ^ ! ~ && || ?? ? : = += -= *= %= **= <<= >>= >>>= &= |= ^= &&= ||= ??= => DivPunctuator :: / /= RightBracePunctuator :: } NullLiteral :: null BooleanLiteral :: true false NumericLiteralSeparator :: _ NumericLiteral :: DecimalLiteral DecimalBigIntegerLiteral NonDecimalIntegerLiteral[+Sep] NonDecimalIntegerLiteral[+Sep] BigIntLiteralSuffix LegacyOctalIntegerLiteral DecimalBigIntegerLiteral :: 0 BigIntLiteralSuffix NonZeroDigit DecimalDigits[+Sep]opt BigIntLiteralSuffix NonZeroDigit NumericLiteralSeparator DecimalDigits[+Sep] BigIntLiteralSuffix NonDecimalIntegerLiteral[Sep] :: BinaryIntegerLiteral[?Sep] OctalIntegerLiteral[?Sep] HexIntegerLiteral[?Sep] BigIntLiteralSuffix :: n DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits[+Sep]opt ExponentPart[+Sep]opt . DecimalDigits[+Sep] ExponentPart[+Sep]opt DecimalIntegerLiteral ExponentPart[+Sep]opt DecimalIntegerLiteral :: 0 NonZeroDigit NonZeroDigit NumericLiteralSeparatoropt DecimalDigits[+Sep] NonOctalDecimalIntegerLiteral DecimalDigits[Sep] :: DecimalDigit DecimalDigits[?Sep] DecimalDigit [+Sep] DecimalDigits[+Sep] NumericLiteralSeparator DecimalDigit DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9 ExponentPart[Sep] :: ExponentIndicator SignedInteger[?Sep] ExponentIndicator :: one of e E SignedInteger[Sep] :: DecimalDigits[?Sep] + DecimalDigits[?Sep] - DecimalDigits[?Sep] BinaryIntegerLiteral[Sep] :: 0b BinaryDigits[?Sep] 0B BinaryDigits[?Sep] BinaryDigits[Sep] :: BinaryDigit BinaryDigits[?Sep] BinaryDigit [+Sep] BinaryDigits[+Sep] NumericLiteralSeparator BinaryDigit BinaryDigit :: one of 0 1 OctalIntegerLiteral[Sep] :: 0o OctalDigits[?Sep] 0O OctalDigits[?Sep] OctalDigits[Sep] :: OctalDigit OctalDigits[?Sep] OctalDigit [+Sep] OctalDigits[+Sep] NumericLiteralSeparator OctalDigit LegacyOctalIntegerLiteral :: 0 OctalDigit LegacyOctalIntegerLiteral OctalDigit NonOctalDecimalIntegerLiteral :: 0 NonOctalDigit LegacyOctalLikeDecimalIntegerLiteral NonOctalDigit NonOctalDecimalIntegerLiteral DecimalDigit LegacyOctalLikeDecimalIntegerLiteral :: 0 OctalDigit LegacyOctalLikeDecimalIntegerLiteral OctalDigit OctalDigit :: one of 0 1 2 3 4 5 6 7 NonOctalDigit :: one of 8 9 HexIntegerLiteral[Sep] :: 0x HexDigits[?Sep] 0X HexDigits[?Sep] HexDigits[Sep] :: HexDigit HexDigits[?Sep] HexDigit [+Sep] HexDigits[+Sep] NumericLiteralSeparator HexDigit HexDigit :: one of 0 1 2 3 4 5 6 7 8 9 a b c d e f A B C D E F StringLiteral :: " DoubleStringCharactersopt " ' SingleStringCharactersopt ' DoubleStringCharacters :: DoubleStringCharacter DoubleStringCharactersopt SingleStringCharacters :: SingleStringCharacter SingleStringCharactersopt DoubleStringCharacter :: SourceCharacter but not one of " or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation SingleStringCharacter :: SourceCharacter but not one of ' or \ or LineTerminator <LS> <PS> \ EscapeSequence LineContinuation LineContinuation :: \ LineTerminatorSequence EscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] LegacyOctalEscapeSequence NonOctalDecimalEscapeSequence HexEscapeSequence UnicodeEscapeSequence CharacterEscapeSequence :: SingleEscapeCharacter NonEscapeCharacter SingleEscapeCharacter :: one of ' " \ b f n r t v NonEscapeCharacter :: SourceCharacter but not one of EscapeCharacter or LineTerminator EscapeCharacter :: SingleEscapeCharacter DecimalDigit x u LegacyOctalEscapeSequence :: 0 [lookahead ∈ { 8, 9 }] NonZeroOctalDigit [lookahead ∉ OctalDigit] ZeroToThree OctalDigit [lookahead ∉ OctalDigit] FourToSeven OctalDigit ZeroToThree OctalDigit OctalDigit NonZeroOctalDigit :: OctalDigit but not 0 ZeroToThree :: one of 0 1 2 3 FourToSeven :: one of 4 5 6 7 NonOctalDecimalEscapeSequence :: one of 8 9 HexEscapeSequence :: x HexDigit HexDigit UnicodeEscapeSequence :: u Hex4Digits u{ CodePoint } Hex4Digits :: HexDigit HexDigit HexDigit HexDigit RegularExpressionLiteral :: / RegularExpressionBody / RegularExpressionFlags RegularExpressionBody :: RegularExpressionFirstChar RegularExpressionChars RegularExpressionChars :: [empty] RegularExpressionChars RegularExpressionChar RegularExpressionFirstChar :: RegularExpressionNonTerminator but not one of * or \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionChar :: RegularExpressionNonTerminator but not one of \ or / or [ RegularExpressionBackslashSequence RegularExpressionClass RegularExpressionBackslashSequence :: \ RegularExpressionNonTerminator RegularExpressionNonTerminator :: SourceCharacter but not LineTerminator RegularExpressionClass :: [ RegularExpressionClassChars ] RegularExpressionClassChars :: [empty] RegularExpressionClassChars RegularExpressionClassChar RegularExpressionClassChar :: RegularExpressionNonTerminator but not one of ] or \ RegularExpressionBackslashSequence RegularExpressionFlags :: [empty] RegularExpressionFlags IdentifierPartChar Template :: NoSubstitutionTemplate TemplateHead NoSubstitutionTemplate :: ` TemplateCharactersopt ` TemplateHead :: ` TemplateCharactersopt ${ TemplateSubstitutionTail :: TemplateMiddle TemplateTail TemplateMiddle :: } TemplateCharactersopt ${ TemplateTail :: } TemplateCharactersopt ` TemplateCharacters :: TemplateCharacter TemplateCharactersopt TemplateCharacter :: $ [lookahead ≠ {] \ TemplateEscapeSequence \ NotEscapeSequence LineContinuation LineTerminatorSequence SourceCharacter but not one of ` or \ or $ or LineTerminator TemplateEscapeSequence :: CharacterEscapeSequence 0 [lookahead ∉ DecimalDigit] HexEscapeSequence UnicodeEscapeSequence NotEscapeSequence :: 0 DecimalDigit DecimalDigit but not 0 x [lookahead ∉ HexDigit] x HexDigit [lookahead ∉ HexDigit] u [lookahead ∉ HexDigit] [lookahead ≠ {] u HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit [lookahead ∉ HexDigit] u HexDigit HexDigit HexDigit [lookahead ∉ HexDigit] u { [lookahead ∉ HexDigit] u { NotCodePoint [lookahead ∉ HexDigit] u { CodePoint [lookahead ∉ HexDigit] [lookahead ≠ }] NotCodePoint :: HexDigits[~Sep] but only if the MV of HexDigits > 0x10FFFF CodePoint :: HexDigits[~Sep] but only if the MV of HexDigits ≤ 0x10FFFF

A.2 Expressions

IdentifierReference[Yield, Await] : Identifier [~Yield] yield [~Await] await BindingIdentifier[Yield, Await] : Identifier yield await LabelIdentifier[Yield, Await] : Identifier [~Yield] yield [~Await] await Identifier : IdentifierName but not ReservedWord PrimaryExpression[Yield, Await] : this IdentifierReference[?Yield, ?Await] Literal ArrayLiteral[?Yield, ?Await] ObjectLiteral[?Yield, ?Await] FunctionExpression ClassExpression[?Yield, ?Await] GeneratorExpression AsyncFunctionExpression AsyncGeneratorExpression RegularExpressionLiteral TemplateLiteral[?Yield, ?Await, ~Tagged] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[Yield, Await] : ( Expression[+In, ?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ) ( ) ( ... BindingIdentifier[?Yield, ?Await] ) ( ... BindingPattern[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingIdentifier[?Yield, ?Await] ) ( Expression[+In, ?Yield, ?Await] , ... BindingPattern[?Yield, ?Await] )

When processing an instance of the production
PrimaryExpression[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
the interpretation of CoverParenthesizedExpressionAndArrowParameterList is refined using the following grammar:

ParenthesizedExpression[Yield, Await] : ( Expression[+In, ?Yield, ?Await] )

 

Literal : NullLiteral BooleanLiteral NumericLiteral StringLiteral ArrayLiteral[Yield, Await] : [ Elisionopt ] [ ElementList[?Yield, ?Await] ] [ ElementList[?Yield, ?Await] , Elisionopt ] ElementList[Yield, Await] : Elisionopt AssignmentExpression[+In, ?Yield, ?Await] Elisionopt SpreadElement[?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt AssignmentExpression[+In, ?Yield, ?Await] ElementList[?Yield, ?Await] , Elisionopt SpreadElement[?Yield, ?Await] Elision : , Elision , SpreadElement[Yield, Await] : ... AssignmentExpression[+In, ?Yield, ?Await] ObjectLiteral[Yield, Await] : { } { PropertyDefinitionList[?Yield, ?Await] } { PropertyDefinitionList[?Yield, ?Await] , } PropertyDefinitionList[Yield, Await] : PropertyDefinition[?Yield, ?Await] PropertyDefinitionList[?Yield, ?Await] , PropertyDefinition[?Yield, ?Await] PropertyDefinition[Yield, Await] : IdentifierReference[?Yield, ?Await] CoverInitializedName[?Yield, ?Await] PropertyName[?Yield, ?Await] : AssignmentExpression[+In, ?Yield, ?Await] MethodDefinition[?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] PropertyName[Yield, Await] : LiteralPropertyName ComputedPropertyName[?Yield, ?Await] LiteralPropertyName : IdentifierName StringLiteral NumericLiteral ComputedPropertyName[Yield, Await] : [ AssignmentExpression[+In, ?Yield, ?Await] ] CoverInitializedName[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await] Initializer[In, Yield, Await] : = AssignmentExpression[?In, ?Yield, ?Await] TemplateLiteral[Yield, Await, Tagged] : NoSubstitutionTemplate SubstitutionTemplate[?Yield, ?Await, ?Tagged] SubstitutionTemplate[Yield, Await, Tagged] : TemplateHead Expression[+In, ?Yield, ?Await] TemplateSpans[?Yield, ?Await, ?Tagged] TemplateSpans[Yield, Await, Tagged] : TemplateTail TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateTail TemplateMiddleList[Yield, Await, Tagged] : TemplateMiddle Expression[+In, ?Yield, ?Await] TemplateMiddleList[?Yield, ?Await, ?Tagged] TemplateMiddle Expression[+In, ?Yield, ?Await] MemberExpression[Yield, Await] : PrimaryExpression[?Yield, ?Await] MemberExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] MemberExpression[?Yield, ?Await] . IdentifierName MemberExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] SuperProperty[?Yield, ?Await] MetaProperty new MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await] MemberExpression[?Yield, ?Await] . PrivateIdentifier SuperProperty[Yield, Await] : super [ Expression[+In, ?Yield, ?Await] ] super . IdentifierName MetaProperty : NewTarget ImportMeta NewTarget : new . target ImportMeta : import . meta NewExpression[Yield, Await] : MemberExpression[?Yield, ?Await] new NewExpression[?Yield, ?Await] CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] SuperCall[?Yield, ?Await] ImportCall[?Yield, ?Await] CallExpression[?Yield, ?Await] Arguments[?Yield, ?Await] CallExpression[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] CallExpression[?Yield, ?Await] . IdentifierName CallExpression[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] CallExpression[?Yield, ?Await] . PrivateIdentifier

When processing an instance of the production
CallExpression[Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await]
the interpretation of CoverCallExpressionAndAsyncArrowHead is refined using the following grammar:

CallMemberExpression[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

 

SuperCall[Yield, Await] : super Arguments[?Yield, ?Await] ImportCall[Yield, Await] : import ( AssignmentExpression[+In, ?Yield, ?Await] ,opt ) import ( AssignmentExpression[+In, ?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ,opt ) Arguments[Yield, Await] : ( ) ( ArgumentList[?Yield, ?Await] ) ( ArgumentList[?Yield, ?Await] , ) ArgumentList[Yield, Await] : AssignmentExpression[+In, ?Yield, ?Await] ... AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , AssignmentExpression[+In, ?Yield, ?Await] ArgumentList[?Yield, ?Await] , ... AssignmentExpression[+In, ?Yield, ?Await] OptionalExpression[Yield, Await] : MemberExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalExpression[?Yield, ?Await] OptionalChain[?Yield, ?Await] OptionalChain[Yield, Await] : ?. Arguments[?Yield, ?Await] ?. [ Expression[+In, ?Yield, ?Await] ] ?. IdentifierName ?. TemplateLiteral[?Yield, ?Await, +Tagged] ?. PrivateIdentifier OptionalChain[?Yield, ?Await] Arguments[?Yield, ?Await] OptionalChain[?Yield, ?Await] [ Expression[+In, ?Yield, ?Await] ] OptionalChain[?Yield, ?Await] . IdentifierName OptionalChain[?Yield, ?Await] TemplateLiteral[?Yield, ?Await, +Tagged] OptionalChain[?Yield, ?Await] . PrivateIdentifier LeftHandSideExpression[Yield, Await] : NewExpression[?Yield, ?Await] CallExpression[?Yield, ?Await] OptionalExpression[?Yield, ?Await] UpdateExpression[Yield, Await] : LeftHandSideExpression[?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] ++ LeftHandSideExpression[?Yield, ?Await] [no LineTerminator here] -- ++ UnaryExpression[?Yield, ?Await] -- UnaryExpression[?Yield, ?Await] UnaryExpression[Yield, Await] : UpdateExpression[?Yield, ?Await] delete UnaryExpression[?Yield, ?Await] void UnaryExpression[?Yield, ?Await] typeof UnaryExpression[?Yield, ?Await] + UnaryExpression[?Yield, ?Await] - UnaryExpression[?Yield, ?Await] ~ UnaryExpression[?Yield, ?Await] ! UnaryExpression[?Yield, ?Await] [+Await] AwaitExpression[?Yield] ExponentiationExpression[Yield, Await] : UnaryExpression[?Yield, ?Await] UpdateExpression[?Yield, ?Await] ** ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[Yield, Await] : ExponentiationExpression[?Yield, ?Await] MultiplicativeExpression[?Yield, ?Await] MultiplicativeOperator ExponentiationExpression[?Yield, ?Await] MultiplicativeOperator : one of * / % AdditiveExpression[Yield, Await] : MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] + MultiplicativeExpression[?Yield, ?Await] AdditiveExpression[?Yield, ?Await] - MultiplicativeExpression[?Yield, ?Await] ShiftExpression[Yield, Await] : AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] << AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >> AdditiveExpression[?Yield, ?Await] ShiftExpression[?Yield, ?Await] >>> AdditiveExpression[?Yield, ?Await] RelationalExpression[In, Yield, Await] : ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] < ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] > ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] <= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] >= ShiftExpression[?Yield, ?Await] RelationalExpression[?In, ?Yield, ?Await] instanceof ShiftExpression[?Yield, ?Await] [+In] RelationalExpression[+In, ?Yield, ?Await] in ShiftExpression[?Yield, ?Await] [+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await] EqualityExpression[In, Yield, Await] : RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] == RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] != RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] === RelationalExpression[?In, ?Yield, ?Await] EqualityExpression[?In, ?Yield, ?Await] !== RelationalExpression[?In, ?Yield, ?Await] BitwiseANDExpression[In, Yield, Await] : EqualityExpression[?In, ?Yield, ?Await] BitwiseANDExpression[?In, ?Yield, ?Await] & EqualityExpression[?In, ?Yield, ?Await] BitwiseXORExpression[In, Yield, Await] : BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseXORExpression[?In, ?Yield, ?Await] ^ BitwiseANDExpression[?In, ?Yield, ?Await] BitwiseORExpression[In, Yield, Await] : BitwiseXORExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] | BitwiseXORExpression[?In, ?Yield, ?Await] LogicalANDExpression[In, Yield, Await] : BitwiseORExpression[?In, ?Yield, ?Await] LogicalANDExpression[?In, ?Yield, ?Await] && BitwiseORExpression[?In, ?Yield, ?Await] LogicalORExpression[In, Yield, Await] : LogicalANDExpression[?In, ?Yield, ?Await] LogicalORExpression[?In, ?Yield, ?Await] || LogicalANDExpression[?In, ?Yield, ?Await] CoalesceExpression[In, Yield, Await] : CoalesceExpressionHead[?In, ?Yield, ?Await] ?? BitwiseORExpression[?In, ?Yield, ?Await] CoalesceExpressionHead[In, Yield, Await] : CoalesceExpression[?In, ?Yield, ?Await] BitwiseORExpression[?In, ?Yield, ?Await] ShortCircuitExpression[In, Yield, Await] : LogicalORExpression[?In, ?Yield, ?Await] CoalesceExpression[?In, ?Yield, ?Await] ConditionalExpression[In, Yield, Await] : ShortCircuitExpression[?In, ?Yield, ?Await] ShortCircuitExpression[?In, ?Yield, ?Await] ? AssignmentExpression[+In, ?Yield, ?Await] : AssignmentExpression[?In, ?Yield, ?Await] AssignmentExpression[In, Yield, Await] : ConditionalExpression[?In, ?Yield, ?Await] [+Yield] YieldExpression[?In, ?Await] ArrowFunction[?In, ?Yield, ?Await] AsyncArrowFunction[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] AssignmentOperator AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] &&= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ||= AssignmentExpression[?In, ?Yield, ?Await] LeftHandSideExpression[?Yield, ?Await] ??= AssignmentExpression[?In, ?Yield, ?Await] AssignmentOperator : one of *= /= %= += -= <<= >>= >>>= &= ^= |= **=

In certain circumstances when processing an instance of the production
AssignmentExpression[In, Yield, Await] : LeftHandSideExpression[?Yield, ?Await] = AssignmentExpression[?In, ?Yield, ?Await]
the interpretation of LeftHandSideExpression is refined using the following grammar:

AssignmentPattern[Yield, Await] : ObjectAssignmentPattern[?Yield, ?Await] ArrayAssignmentPattern[?Yield, ?Await] ObjectAssignmentPattern[Yield, Await] : { } { AssignmentRestProperty[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] } { AssignmentPropertyList[?Yield, ?Await] , AssignmentRestProperty[?Yield, ?Await]opt } ArrayAssignmentPattern[Yield, Await] : [ Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] [ AssignmentElementList[?Yield, ?Await] ] [ AssignmentElementList[?Yield, ?Await] , Elisionopt AssignmentRestElement[?Yield, ?Await]opt ] AssignmentRestProperty[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] AssignmentPropertyList[Yield, Await] : AssignmentProperty[?Yield, ?Await] AssignmentPropertyList[?Yield, ?Await] , AssignmentProperty[?Yield, ?Await] AssignmentElementList[Yield, Await] : AssignmentElisionElement[?Yield, ?Await] AssignmentElementList[?Yield, ?Await] , AssignmentElisionElement[?Yield, ?Await] AssignmentElisionElement[Yield, Await] : Elisionopt AssignmentElement[?Yield, ?Await] AssignmentProperty[Yield, Await] : IdentifierReference[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt PropertyName[?Yield, ?Await] : AssignmentElement[?Yield, ?Await] AssignmentElement[Yield, Await] : DestructuringAssignmentTarget[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt AssignmentRestElement[Yield, Await] : ... DestructuringAssignmentTarget[?Yield, ?Await] DestructuringAssignmentTarget[Yield, Await] : LeftHandSideExpression[?Yield, ?Await]

 

Expression[In, Yield, Await] : AssignmentExpression[?In, ?Yield, ?Await] Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]

A.3 Statements

Statement[Yield, Await, Return] : BlockStatement[?Yield, ?Await, ?Return] VariableStatement[?Yield, ?Await] EmptyStatement ExpressionStatement[?Yield, ?Await] IfStatement[?Yield, ?Await, ?Return] BreakableStatement[?Yield, ?Await, ?Return] ContinueStatement[?Yield, ?Await] BreakStatement[?Yield, ?Await] [+Return] ReturnStatement[?Yield, ?Await] WithStatement[?Yield, ?Await, ?Return] LabelledStatement[?Yield, ?Await, ?Return] ThrowStatement[?Yield, ?Await] TryStatement[?Yield, ?Await, ?Return] DebuggerStatement Declaration[Yield, Await] : HoistableDeclaration[?Yield, ?Await, ~Default] ClassDeclaration[?Yield, ?Await, ~Default] LexicalDeclaration[+In, ?Yield, ?Await] HoistableDeclaration[Yield, Await, Default] : FunctionDeclaration[?Yield, ?Await, ?Default] GeneratorDeclaration[?Yield, ?Await, ?Default] AsyncFunctionDeclaration[?Yield, ?Await, ?Default] AsyncGeneratorDeclaration[?Yield, ?Await, ?Default] BreakableStatement[Yield, Await, Return] : IterationStatement[?Yield, ?Await, ?Return] SwitchStatement[?Yield, ?Await, ?Return] BlockStatement[Yield, Await, Return] : Block[?Yield, ?Await, ?Return] Block[Yield, Await, Return] : { StatementList[?Yield, ?Await, ?Return]opt } StatementList[Yield, Await, Return] : StatementListItem[?Yield, ?Await, ?Return] StatementList[?Yield, ?Await, ?Return] StatementListItem[?Yield, ?Await, ?Return] StatementListItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] Declaration[?Yield, ?Await] LexicalDeclaration[In, Yield, Await] : LetOrConst BindingList[?In, ?Yield, ?Await] ; LetOrConst : let const BindingList[In, Yield, Await] : LexicalBinding[?In, ?Yield, ?Await] BindingList[?In, ?Yield, ?Await] , LexicalBinding[?In, ?Yield, ?Await] LexicalBinding[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] VariableStatement[Yield, Await] : var VariableDeclarationList[+In, ?Yield, ?Await] ; VariableDeclarationList[In, Yield, Await] : VariableDeclaration[?In, ?Yield, ?Await] VariableDeclarationList[?In, ?Yield, ?Await] , VariableDeclaration[?In, ?Yield, ?Await] VariableDeclaration[In, Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]opt BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await] BindingPattern[Yield, Await] : ObjectBindingPattern[?Yield, ?Await] ArrayBindingPattern[?Yield, ?Await] ObjectBindingPattern[Yield, Await] : { } { BindingRestProperty[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] } { BindingPropertyList[?Yield, ?Await] , BindingRestProperty[?Yield, ?Await]opt } ArrayBindingPattern[Yield, Await] : [ Elisionopt BindingRestElement[?Yield, ?Await]opt ] [ BindingElementList[?Yield, ?Await] ] [ BindingElementList[?Yield, ?Await] , Elisionopt BindingRestElement[?Yield, ?Await]opt ] BindingRestProperty[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] BindingPropertyList[Yield, Await] : BindingProperty[?Yield, ?Await] BindingPropertyList[?Yield, ?Await] , BindingProperty[?Yield, ?Await] BindingElementList[Yield, Await] : BindingElisionElement[?Yield, ?Await] BindingElementList[?Yield, ?Await] , BindingElisionElement[?Yield, ?Await] BindingElisionElement[Yield, Await] : Elisionopt BindingElement[?Yield, ?Await] BindingProperty[Yield, Await] : SingleNameBinding[?Yield, ?Await] PropertyName[?Yield, ?Await] : BindingElement[?Yield, ?Await] BindingElement[Yield, Await] : SingleNameBinding[?Yield, ?Await] BindingPattern[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt SingleNameBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt BindingRestElement[Yield, Await] : ... BindingIdentifier[?Yield, ?Await] ... BindingPattern[?Yield, ?Await] EmptyStatement : ; ExpressionStatement[Yield, Await] : [lookahead ∉ { {, function, async [no LineTerminator here] function, class, let [ }] Expression[+In, ?Yield, ?Await] ; IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [lookahead ≠ else] IterationStatement[Yield, Await, Return] : DoWhileStatement[?Yield, ?Await, ?Return] WhileStatement[?Yield, ?Await, ?Return] ForStatement[?Yield, ?Await, ?Return] ForInOfStatement[?Yield, ?Await, ?Return] DoWhileStatement[Yield, Await, Return] : do Statement[?Yield, ?Await, ?Return] while ( Expression[+In, ?Yield, ?Await] ) ; WhileStatement[Yield, Await, Return] : while ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] Expression[~In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( var VariableDeclarationList[~In, ?Yield, ?Await] ; Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] for ( LexicalDeclaration[~In, ?Yield, ?Await] Expression[+In, ?Yield, ?Await]opt ; Expression[+In, ?Yield, ?Await]opt ) Statement[?Yield, ?Await, ?Return] ForInOfStatement[Yield, Await, Return] : for ( [lookahead ≠ let [] LeftHandSideExpression[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( [lookahead ∉ { let, async of }] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] for ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( [lookahead ≠ let] LeftHandSideExpression[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( var ForBinding[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] [+Await] for await ( ForDeclaration[?Yield, ?Await] of AssignmentExpression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] ForDeclaration[Yield, Await] : LetOrConst ForBinding[?Yield, ?Await] ForBinding[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] ContinueStatement[Yield, Await] : continue ; continue [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; BreakStatement[Yield, Await] : break ; break [no LineTerminator here] LabelIdentifier[?Yield, ?Await] ; ReturnStatement[Yield, Await] : return ; return [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; WithStatement[Yield, Await, Return] : with ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] SwitchStatement[Yield, Await, Return] : switch ( Expression[+In, ?Yield, ?Await] ) CaseBlock[?Yield, ?Await, ?Return] CaseBlock[Yield, Await, Return] : { CaseClauses[?Yield, ?Await, ?Return]opt } { CaseClauses[?Yield, ?Await, ?Return]opt DefaultClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return]opt } CaseClauses[Yield, Await, Return] : CaseClause[?Yield, ?Await, ?Return] CaseClauses[?Yield, ?Await, ?Return] CaseClause[?Yield, ?Await, ?Return] CaseClause[Yield, Await, Return] : case Expression[+In, ?Yield, ?Await] : StatementList[?Yield, ?Await, ?Return]opt DefaultClause[Yield, Await, Return] : default : StatementList[?Yield, ?Await, ?Return]opt LabelledStatement[Yield, Await, Return] : LabelIdentifier[?Yield, ?Await] : LabelledItem[?Yield, ?Await, ?Return] LabelledItem[Yield, Await, Return] : Statement[?Yield, ?Await, ?Return] FunctionDeclaration[?Yield, ?Await, ~Default] ThrowStatement[Yield, Await] : throw [no LineTerminator here] Expression[+In, ?Yield, ?Await] ; TryStatement[Yield, Await, Return] : try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] try Block[?Yield, ?Await, ?Return] Catch[?Yield, ?Await, ?Return] Finally[?Yield, ?Await, ?Return] Catch[Yield, Await, Return] : catch ( CatchParameter[?Yield, ?Await] ) Block[?Yield, ?Await, ?Return] catch Block[?Yield, ?Await, ?Return] Finally[Yield, Await, Return] : finally Block[?Yield, ?Await, ?Return] CatchParameter[Yield, Await] : BindingIdentifier[?Yield, ?Await] BindingPattern[?Yield, ?Await] DebuggerStatement : debugger ;

A.4 Functions and Classes

UniqueFormalParameters[Yield, Await] : FormalParameters[?Yield, ?Await] FormalParameters[Yield, Await] : [empty] FunctionRestParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameterList[?Yield, ?Await] , FunctionRestParameter[?Yield, ?Await] FormalParameterList[Yield, Await] : FormalParameter[?Yield, ?Await] FormalParameterList[?Yield, ?Await] , FormalParameter[?Yield, ?Await] FunctionRestParameter[Yield, Await] : BindingRestElement[?Yield, ?Await] FormalParameter[Yield, Await] : BindingElement[?Yield, ?Await] FunctionDeclaration[Yield, Await, Default] : function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } [+Default] function ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionExpression : function BindingIdentifier[~Yield, ~Await]opt ( FormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } FunctionBody[Yield, Await] : FunctionStatementList[?Yield, ?Await] FunctionStatementList[Yield, Await] : StatementList[?Yield, ?Await, +Return]opt ArrowFunction[In, Yield, Await] : ArrowParameters[?Yield, ?Await] [no LineTerminator here] => ConciseBody[?In] ArrowParameters[Yield, Await] : BindingIdentifier[?Yield, ?Await] CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await] ConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, ~Await] { FunctionBody[~Yield, ~Await] } ExpressionBody[In, Await] : AssignmentExpression[?In, ~Yield, ?Await]

When processing an instance of the production
ArrowParameters[Yield, Await] : CoverParenthesizedExpressionAndArrowParameterList[?Yield, ?Await]
the interpretation of CoverParenthesizedExpressionAndArrowParameterList is refined using the following grammar:

ArrowFormalParameters[Yield, Await] : ( UniqueFormalParameters[?Yield, ?Await] )

 

AsyncArrowFunction[In, Yield, Await] : async [no LineTerminator here] AsyncArrowBindingIdentifier[?Yield] [no LineTerminator here] => AsyncConciseBody[?In] CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In] AsyncConciseBody[In] : [lookahead ≠ {] ExpressionBody[?In, +Await] { AsyncFunctionBody } AsyncArrowBindingIdentifier[Yield] : BindingIdentifier[?Yield, +Await] CoverCallExpressionAndAsyncArrowHead[Yield, Await] : MemberExpression[?Yield, ?Await] Arguments[?Yield, ?Await]

When processing an instance of the production
AsyncArrowFunction[In, Yield, Await] : CoverCallExpressionAndAsyncArrowHead[?Yield, ?Await] [no LineTerminator here] => AsyncConciseBody[?In]
the interpretation of CoverCallExpressionAndAsyncArrowHead is refined using the following grammar:

AsyncArrowHead : async [no LineTerminator here] ArrowFormalParameters[~Yield, +Await]

 

MethodDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, ~Await] ) { FunctionBody[~Yield, ~Await] } GeneratorMethod[?Yield, ?Await] AsyncMethod[?Yield, ?Await] AsyncGeneratorMethod[?Yield, ?Await] get ClassElementName[?Yield, ?Await] ( ) { FunctionBody[~Yield, ~Await] } set ClassElementName[?Yield, ?Await] ( PropertySetParameterList ) { FunctionBody[~Yield, ~Await] } PropertySetParameterList : FormalParameter[~Yield, ~Await] GeneratorDeclaration[Yield, Await, Default] : function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } [+Default] function * ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorExpression : function * BindingIdentifier[+Yield, ~Await]opt ( FormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorMethod[Yield, Await] : * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody } GeneratorBody : FunctionBody[+Yield, ~Await] YieldExpression[In, Await] : yield yield [no LineTerminator here] AssignmentExpression[?In, +Yield, ?Await] yield [no LineTerminator here] * AssignmentExpression[?In, +Yield, ?Await] AsyncGeneratorDeclaration[Yield, Await, Default] : async [no LineTerminator here] function * BindingIdentifier[?Yield, ?Await] ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } [+Default] async [no LineTerminator here] function * ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorExpression : async [no LineTerminator here] function * BindingIdentifier[+Yield, +Await]opt ( FormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorMethod[Yield, Await] : async [no LineTerminator here] * ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, +Await] ) { AsyncGeneratorBody } AsyncGeneratorBody : FunctionBody[+Yield, +Await] AsyncFunctionDeclaration[Yield, Await, Default] : async [no LineTerminator here] function BindingIdentifier[?Yield, ?Await] ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } [+Default] async [no LineTerminator here] function ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionExpression : async [no LineTerminator here] function BindingIdentifier[~Yield, +Await]opt ( FormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncMethod[Yield, Await] : async [no LineTerminator here] ClassElementName[?Yield, ?Await] ( UniqueFormalParameters[~Yield, +Await] ) { AsyncFunctionBody } AsyncFunctionBody : FunctionBody[~Yield, +Await] AwaitExpression[Yield] : await UnaryExpression[?Yield, +Await] ClassDeclaration[Yield, Await, Default] : class BindingIdentifier[?Yield, ?Await] ClassTail[?Yield, ?Await] [+Default] class ClassTail[?Yield, ?Await] ClassExpression[Yield, Await] : class BindingIdentifier[?Yield, ?Await]opt ClassTail[?Yield, ?Await] ClassTail[Yield, Await] : ClassHeritage[?Yield, ?Await]opt { ClassBody[?Yield, ?Await]opt } ClassHeritage[Yield, Await] : extends LeftHandSideExpression[?Yield, ?Await] ClassBody[Yield, Await] : ClassElementList[?Yield, ?Await] ClassElementList[Yield, Await] : ClassElement[?Yield, ?Await] ClassElementList[?Yield, ?Await] ClassElement[?Yield, ?Await] ClassElement[Yield, Await] : MethodDefinition[?Yield, ?Await] static MethodDefinition[?Yield, ?Await] FieldDefinition[?Yield, ?Await] ; static FieldDefinition[?Yield, ?Await] ; ClassStaticBlock ; FieldDefinition[Yield, Await] : ClassElementName[?Yield, ?Await] Initializer[+In, ?Yield, ?Await]opt ClassElementName[Yield, Await] : PropertyName[?Yield, ?Await] PrivateIdentifier ClassStaticBlock : static { ClassStaticBlockBody } ClassStaticBlockBody : ClassStaticBlockStatementList ClassStaticBlockStatementList : StatementList[~Yield, +Await, ~Return]opt

A.5 Scripts and Modules

Script : ScriptBodyopt ScriptBody : StatementList[~Yield, ~Await, ~Return] Module : ModuleBodyopt ModuleBody : ModuleItemList ModuleItemList : ModuleItem ModuleItemList ModuleItem ModuleItem : ImportDeclaration ExportDeclaration StatementListItem[~Yield, +Await, ~Return] ModuleExportName : IdentifierName StringLiteral ImportDeclaration : import ImportClause FromClause WithClauseopt ; import ModuleSpecifier WithClauseopt ; ImportClause : ImportedDefaultBinding NameSpaceImport NamedImports ImportedDefaultBinding , NameSpaceImport ImportedDefaultBinding , NamedImports ImportedDefaultBinding : ImportedBinding NameSpaceImport : * as ImportedBinding NamedImports : { } { ImportsList } { ImportsList , } FromClause : from ModuleSpecifier ImportsList : ImportSpecifier ImportsList , ImportSpecifier ImportSpecifier : ImportedBinding ModuleExportName as ImportedBinding ModuleSpecifier : StringLiteral ImportedBinding : BindingIdentifier[~Yield, +Await] WithClause : with { } with { WithEntries ,opt } WithEntries : AttributeKey : StringLiteral AttributeKey : StringLiteral , WithEntries AttributeKey : IdentifierName StringLiteral ExportDeclaration : export ExportFromClause FromClause WithClauseopt ; export NamedExports ; export VariableStatement[~Yield, +Await] export Declaration[~Yield, +Await] export default HoistableDeclaration[~Yield, +Await, +Default] export default ClassDeclaration[~Yield, +Await, +Default] export default [lookahead ∉ { function, async [no LineTerminator here] function, class }] AssignmentExpression[+In, ~Yield, +Await] ; ExportFromClause : * * as ModuleExportName NamedExports NamedExports : { } { ExportsList } { ExportsList , } ExportsList : ExportSpecifier ExportsList , ExportSpecifier ExportSpecifier : ModuleExportName ModuleExportName as ModuleExportName

A.6 Number Conversions

StringNumericLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrNumericLiteral StrWhiteSpaceopt StrWhiteSpace ::: StrWhiteSpaceChar StrWhiteSpaceopt StrWhiteSpaceChar ::: WhiteSpace LineTerminator StrNumericLiteral ::: StrDecimalLiteral NonDecimalIntegerLiteral[~Sep] StrDecimalLiteral ::: StrUnsignedDecimalLiteral + StrUnsignedDecimalLiteral - StrUnsignedDecimalLiteral StrUnsignedDecimalLiteral ::: Infinity DecimalDigits[~Sep] . DecimalDigits[~Sep]opt ExponentPart[~Sep]opt . DecimalDigits[~Sep] ExponentPart[~Sep]opt DecimalDigits[~Sep] ExponentPart[~Sep]opt

All grammar symbols not explicitly defined by the StringNumericLiteral grammar have the definitions used in the Lexical Grammar for numeric literals.

StringIntegerLiteral ::: StrWhiteSpaceopt StrWhiteSpaceopt StrIntegerLiteral StrWhiteSpaceopt StrIntegerLiteral ::: SignedInteger[~Sep] NonDecimalIntegerLiteral[~Sep]

A.7 Time Zone Offset String Format

UTCOffset ::: ASCIISign Hour ASCIISign Hour HourSubcomponents[+Extended] ASCIISign Hour HourSubcomponents[~Extended] ASCIISign ::: one of + - Hour ::: 0 DecimalDigit 1 DecimalDigit 20 21 22 23 HourSubcomponents[Extended] ::: TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TimeSeparator[?Extended] MinuteSecond TemporalDecimalFractionopt TimeSeparator[Extended] ::: [+Extended] : [~Extended] [empty] MinuteSecond ::: 0 DecimalDigit 1 DecimalDigit 2 DecimalDigit 3 DecimalDigit 4 DecimalDigit 5 DecimalDigit TemporalDecimalFraction ::: TemporalDecimalSeparator DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit DecimalDigit TemporalDecimalSeparator ::: one of . ,

A.8 Regular Expressions

Pattern[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Disjunction[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] | Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Alternative[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [empty] Alternative[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: Assertion[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Atom[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B (?= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) Quantifier :: QuantifierPrefix QuantifierPrefix ? QuantifierPrefix :: * + ? { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } Atom[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: PatternCharacter . \ AtomEscape[?UnicodeMode, ?NamedCaptureGroups] CharacterClass[?UnicodeMode, ?UnicodeSetsMode] ( GroupSpecifier[?UnicodeMode]opt Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) RegularExpressionModifiers :: [empty] RegularExpressionModifiers RegularExpressionModifier RegularExpressionModifier :: one of i m s SyntaxCharacter :: one of ^ $ \ . * + ? ( ) [ ] { } | PatternCharacter :: SourceCharacter but not SyntaxCharacter AtomEscape[UnicodeMode, NamedCaptureGroups] :: DecimalEscape CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] IdentityEscape[?UnicodeMode] ControlEscape :: one of f n r t v GroupSpecifier[UnicodeMode] :: ? GroupName[?UnicodeMode] GroupName[UnicodeMode] :: < RegExpIdentifierName[?UnicodeMode] > RegExpIdentifierName[UnicodeMode] :: RegExpIdentifierStart[?UnicodeMode] RegExpIdentifierName[?UnicodeMode] RegExpIdentifierPart[?UnicodeMode] RegExpIdentifierStart[UnicodeMode] :: IdentifierStartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpIdentifierPart[UnicodeMode] :: IdentifierPartChar \ RegExpUnicodeEscapeSequence[+UnicodeMode] [~UnicodeMode] UnicodeLeadSurrogate UnicodeTrailSurrogate RegExpUnicodeEscapeSequence[UnicodeMode] :: [+UnicodeMode] u HexLeadSurrogate \u HexTrailSurrogate [+UnicodeMode] u HexLeadSurrogate [+UnicodeMode] u HexTrailSurrogate [+UnicodeMode] u HexNonSurrogate [~UnicodeMode] u Hex4Digits [+UnicodeMode] u{ CodePoint } UnicodeLeadSurrogate :: any Unicode code point in the inclusive interval from U+D800 to U+DBFF UnicodeTrailSurrogate :: any Unicode code point in the inclusive interval from U+DC00 to U+DFFF

Each \u HexTrailSurrogate for which the choice of associated u HexLeadSurrogate is ambiguous shall be associated with the nearest possible u HexLeadSurrogate that would otherwise have no corresponding \u HexTrailSurrogate.

 

HexLeadSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xD800 to 0xDBFF HexTrailSurrogate :: Hex4Digits but only if the MV of Hex4Digits is in the inclusive interval from 0xDC00 to 0xDFFF HexNonSurrogate :: Hex4Digits but only if the MV of Hex4Digits is not in the inclusive interval from 0xD800 to 0xDFFF IdentityEscape[UnicodeMode] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacter but not UnicodeIDContinue DecimalEscape :: NonZeroDigit DecimalDigits[~Sep]opt [lookahead ∉ DecimalDigit] CharacterClassEscape[UnicodeMode] :: d D s S w W [+UnicodeMode] p{ UnicodePropertyValueExpression } [+UnicodeMode] P{ UnicodePropertyValueExpression } UnicodePropertyValueExpression :: UnicodePropertyName = UnicodePropertyValue LoneUnicodePropertyNameOrValue UnicodePropertyName :: UnicodePropertyNameCharacters UnicodePropertyNameCharacters :: UnicodePropertyNameCharacter UnicodePropertyNameCharactersopt UnicodePropertyValue :: UnicodePropertyValueCharacters LoneUnicodePropertyNameOrValue :: UnicodePropertyValueCharacters UnicodePropertyValueCharacters :: UnicodePropertyValueCharacter UnicodePropertyValueCharactersopt UnicodePropertyValueCharacter :: UnicodePropertyNameCharacter DecimalDigit UnicodePropertyNameCharacter :: AsciiLetter _ CharacterClass[UnicodeMode, UnicodeSetsMode] :: [ [lookahead ≠ ^] ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] [^ ClassContents[?UnicodeMode, ?UnicodeSetsMode] ] ClassContents[UnicodeMode, UnicodeSetsMode] :: [empty] [~UnicodeSetsMode] NonemptyClassRanges[?UnicodeMode] [+UnicodeSetsMode] ClassSetExpression NonemptyClassRanges[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtom[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtom[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] NonemptyClassRangesNoDash[UnicodeMode] :: ClassAtom[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] NonemptyClassRangesNoDash[?UnicodeMode] ClassAtomNoDash[?UnicodeMode] - ClassAtom[?UnicodeMode] ClassContents[?UnicodeMode, ~UnicodeSetsMode] ClassAtom[UnicodeMode] :: - ClassAtomNoDash[?UnicodeMode] ClassAtomNoDash[UnicodeMode] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode] ClassEscape[UnicodeMode] :: b [+UnicodeMode] - CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode] ClassSetExpression :: ClassUnion ClassIntersection ClassSubtraction ClassUnion :: ClassSetRange ClassUnionopt ClassSetOperand ClassUnionopt ClassIntersection :: ClassSetOperand && [lookahead ≠ &] ClassSetOperand ClassIntersection && [lookahead ≠ &] ClassSetOperand ClassSubtraction :: ClassSetOperand -- ClassSetOperand ClassSubtraction -- ClassSetOperand ClassSetRange :: ClassSetCharacter - ClassSetCharacter ClassSetOperand :: NestedClass ClassStringDisjunction ClassSetCharacter NestedClass :: [ [lookahead ≠ ^] ClassContents[+UnicodeMode, +UnicodeSetsMode] ] [^ ClassContents[+UnicodeMode, +UnicodeSetsMode] ] \ CharacterClassEscape[+UnicodeMode] ClassStringDisjunction :: \q{ ClassStringDisjunctionContents } ClassStringDisjunctionContents :: ClassString ClassString | ClassStringDisjunctionContents ClassString :: [empty] NonEmptyClassString NonEmptyClassString :: ClassSetCharacter NonEmptyClassStringopt ClassSetCharacter :: [lookahead ∉ ClassSetReservedDoublePunctuator] SourceCharacter but not ClassSetSyntaxCharacter \ CharacterEscape[+UnicodeMode] \ ClassSetReservedPunctuator \b ClassSetReservedDoublePunctuator :: one of && !! ## $$ %% ** ++ ,, .. :: ;; << == >> ?? @@ ^^ `` ~~ ClassSetSyntaxCharacter :: one of ( ) [ ] { } / - \ | ClassSetReservedPunctuator :: one of & - ! # % , : ; < = > @ ` ~

Annex B (normative) Additional ECMAScript Features for Web Browsers

The ECMAScript language syntax and semantics defined in this annex are required when the ECMAScript host is a web browser. The content of this annex is normative but optional if the ECMAScript host is not a web browser.

Note

This annex describes various legacy features and other characteristics of web browser ECMAScript hosts. All of the language features and behaviours specified in this annex have one or more undesirable characteristics and in the absence of legacy usage would be removed from this specification. However, the usage of these features by large numbers of existing web pages means that web browsers must continue to support them. The specifications in this annex define the requirements for interoperable implementations of these legacy features.

These features are not considered part of the core ECMAScript language. Programmers should not use or assume the existence of these features and behaviours when writing new ECMAScript code. ECMAScript implementations are discouraged from implementing these features unless the implementation is part of a web browser or is required to run the same legacy ECMAScript code that web browsers encounter.

B.1 Additional Syntax

B.1.1 HTML-like Comments

The syntax and semantics of 12.4 is extended as follows except that this extension is not allowed when parsing source text using the goal symbol Module:

Syntax

InputElementHashbangOrRegExp :: WhiteSpace LineTerminator Comment CommonToken HashbangComment RegularExpressionLiteral HTMLCloseComment Comment :: MultiLineComment SingleLineComment SingleLineHTMLOpenComment SingleLineHTMLCloseComment SingleLineDelimitedComment MultiLineComment :: /* FirstCommentLineopt LineTerminator MultiLineCommentCharsopt */ HTMLCloseCommentopt FirstCommentLine :: SingleLineDelimitedCommentChars SingleLineHTMLOpenComment :: <!-- SingleLineCommentCharsopt SingleLineHTMLCloseComment :: LineTerminatorSequence HTMLCloseComment SingleLineDelimitedComment :: /* SingleLineDelimitedCommentCharsopt */ HTMLCloseComment :: WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt --> SingleLineCommentCharsopt SingleLineDelimitedCommentChars :: SingleLineNotAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotAsteriskChar :: SourceCharacter but not one of * or LineTerminator SingleLinePostAsteriskCommentChars :: SingleLineNotForwardSlashOrAsteriskChar SingleLineDelimitedCommentCharsopt * SingleLinePostAsteriskCommentCharsopt SingleLineNotForwardSlashOrAsteriskChar :: SourceCharacter but not one of / or * or LineTerminator WhiteSpaceSequence :: WhiteSpace WhiteSpaceSequenceopt SingleLineDelimitedCommentSequence :: SingleLineDelimitedComment WhiteSpaceSequenceopt SingleLineDelimitedCommentSequenceopt

Similar to a MultiLineComment that contains a line terminator code point, a SingleLineHTMLCloseComment is considered to be a LineTerminator for purposes of parsing by the syntactic grammar.

B.1.2 Regular Expressions Patterns

The syntax of 22.2.1 is modified and extended as follows. These changes introduce ambiguities that are broken by the ordering of grammar productions and by contextual information. When parsing using the following grammar, each alternative is considered only if previous production alternatives do not match.

This alternative pattern grammar and semantics only changes the syntax and semantics of BMP patterns. The following grammar extensions include productions parameterized with the [UnicodeMode] parameter. However, none of these extensions change the syntax of Unicode patterns recognized when parsing with the [UnicodeMode] parameter present on the goal symbol.

Syntax

Term[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: [+UnicodeMode] Assertion[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] Quantifier [+UnicodeMode] Atom[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] Quantifier [~UnicodeMode] Assertion[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Quantifier [~UnicodeMode] ExtendedAtom[?NamedCaptureGroups] Assertion[UnicodeMode, UnicodeSetsMode, NamedCaptureGroups] :: ^ $ \b \B [+UnicodeMode] (?= Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [+UnicodeMode] (?! Disjunction[+UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) [~UnicodeMode] QuantifiableAssertion[?NamedCaptureGroups] (?<= Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) (?<! Disjunction[?UnicodeMode, ?UnicodeSetsMode, ?NamedCaptureGroups] ) QuantifiableAssertion[NamedCaptureGroups] :: (?= Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (?! Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) ExtendedAtom[NamedCaptureGroups] :: . \ AtomEscape[~UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] CharacterClass[~UnicodeMode, ~UnicodeSetsMode] ( GroupSpecifier[~UnicodeMode]opt Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) (? RegularExpressionModifiers - RegularExpressionModifiers : Disjunction[~UnicodeMode, ~UnicodeSetsMode, ?NamedCaptureGroups] ) InvalidBracedQuantifier ExtendedPatternCharacter InvalidBracedQuantifier :: { DecimalDigits[~Sep] } { DecimalDigits[~Sep] ,} { DecimalDigits[~Sep] , DecimalDigits[~Sep] } ExtendedPatternCharacter :: SourceCharacter but not one of ^ $ \ . * + ? ( ) [ | AtomEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] DecimalEscape [~UnicodeMode] DecimalEscape but only if the CapturingGroupNumber of DecimalEscape is ≤ CountLeftCapturingParensWithin(the Pattern containing DecimalEscape) CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] [+NamedCaptureGroups] k GroupName[?UnicodeMode] CharacterEscape[UnicodeMode, NamedCaptureGroups] :: ControlEscape c AsciiLetter 0 [lookahead ∉ DecimalDigit] HexEscapeSequence RegExpUnicodeEscapeSequence[?UnicodeMode] [~UnicodeMode] LegacyOctalEscapeSequence IdentityEscape[?UnicodeMode, ?NamedCaptureGroups] IdentityEscape[UnicodeMode, NamedCaptureGroups] :: [+UnicodeMode] SyntaxCharacter [+UnicodeMode] / [~UnicodeMode] SourceCharacterIdentityEscape[?NamedCaptureGroups] SourceCharacterIdentityEscape[NamedCaptureGroups] :: [~NamedCaptureGroups] SourceCharacter but not c [+NamedCaptureGroups] SourceCharacter but not one of c or k ClassAtomNoDash[UnicodeMode, NamedCaptureGroups] :: SourceCharacter but not one of \ or ] or - \ ClassEscape[?UnicodeMode, ?NamedCaptureGroups] \ [lookahead = c] ClassEscape[UnicodeMode, NamedCaptureGroups] :: b [+UnicodeMode] - [~UnicodeMode] c ClassControlLetter CharacterClassEscape[?UnicodeMode] CharacterEscape[?UnicodeMode, ?NamedCaptureGroups] ClassControlLetter :: DecimalDigit _ Note

When the same left-hand sides occurs with both [+UnicodeMode] and [~UnicodeMode] guards it is to control the disambiguation priority.

B.1.2.1 Static Semantics: Early Errors

The semantics of 22.2.1.1 is extended as follows:

ExtendedAtom :: InvalidBracedQuantifier
  • It is a Syntax Error if any source text is matched by this production.

Additionally, the rules for the following productions are modified with the addition of the highlighted text:

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents

B.1.2.2 Static Semantics: CountLeftCapturingParensWithin and CountLeftCapturingParensBefore

In the definitions of CountLeftCapturingParensWithin and CountLeftCapturingParensBefore, references to “ Atom :: ( GroupSpecifieropt Disjunction ) ” are to be interpreted as meaning “ Atom :: ( GroupSpecifieropt Disjunction ) ” or “ ExtendedAtom :: ( GroupSpecifieropt Disjunction ) ”.

B.1.2.3 Static Semantics: IsCharacterClass

The semantics of 22.2.1.6 is extended as follows:

ClassAtomNoDash :: \ [lookahead = c]
  1. Return false.

B.1.2.4 Static Semantics: CharacterValue

The semantics of 22.2.1.7 is extended as follows:

ClassAtomNoDash :: \ [lookahead = c]
  1. Return the numeric value of U+005C (REVERSE SOLIDUS).
ClassEscape :: c ClassControlLetter
  1. Let ch be the code point matched by ClassControlLetter.
  2. Let i be the numeric value of ch.
  3. Return the remainder of dividing i by 32.
CharacterEscape :: LegacyOctalEscapeSequence
  1. Return the MV of LegacyOctalEscapeSequence (see 12.9.4.3).

B.1.2.5 Runtime Semantics: CompileSubpattern

The semantics of CompileSubpattern is extended as follows:

The rule for Term :: QuantifiableAssertion Quantifier is the same as for Term :: Atom Quantifier but with QuantifiableAssertion substituted for Atom.

The rule for Term :: ExtendedAtom Quantifier is the same as for Term :: Atom Quantifier but with ExtendedAtom substituted for Atom.

The rule for Term :: ExtendedAtom is the same as for Term :: Atom but with ExtendedAtom substituted for Atom.

B.1.2.6 Runtime Semantics: CompileAssertion

CompileAssertion rules for the Assertion :: (?= Disjunction ) and Assertion :: (?! Disjunction ) productions are also used for the QuantifiableAssertion productions, but with QuantifiableAssertion substituted for Assertion.

B.1.2.7 Runtime Semantics: CompileAtom

CompileAtom rules for the Atom productions except for Atom :: PatternCharacter are also used for the ExtendedAtom productions, but with ExtendedAtom substituted for Atom. The following rules, with parameter direction, are also added:

ExtendedAtom :: \ [lookahead = c]
  1. Let A be the CharSet containing the single character \ U+005C (REVERSE SOLIDUS).
  2. Return CharacterSetMatcher(rer, A, false, direction).
ExtendedAtom :: ExtendedPatternCharacter
  1. Let ch be the character represented by ExtendedPatternCharacter.
  2. Let A be a one-element CharSet containing the character ch.
  3. Return CharacterSetMatcher(rer, A, false, direction).

B.1.2.8 Runtime Semantics: CompileToCharSet

The semantics of 22.2.2.9 is extended as follows:

The following two rules replace the corresponding rules of CompileToCharSet.

NonemptyClassRanges :: ClassAtom - ClassAtom ClassContents
  1. Let A be CompileToCharSet of the first ClassAtom with argument rer.
  2. Let B be CompileToCharSet of the second ClassAtom with argument rer.
  3. Let C be CompileToCharSet of ClassContents with argument rer.
  4. Let D be CharacterRangeOrUnion(rer, A, B).
  5. Return the union of D and C.
NonemptyClassRangesNoDash :: ClassAtomNoDash - ClassAtom ClassContents
  1. Let A be CompileToCharSet of ClassAtomNoDash with argument rer.
  2. Let B be CompileToCharSet of ClassAtom with argument rer.
  3. Let C be CompileToCharSet of ClassContents with argument rer.
  4. Let D be CharacterRangeOrUnion(rer, A, B).
  5. Return the union of D and C.

In addition, the following rules are added to CompileToCharSet.

ClassEscape :: c ClassControlLetter
  1. Let cv be the CharacterValue of this ClassEscape.
  2. Let c be the character whose character value is cv.
  3. Return the CharSet containing the single character c.
ClassAtomNoDash :: \ [lookahead = c]
  1. Return the CharSet containing the single character \ U+005C (REVERSE SOLIDUS).
Note
This production can only be reached from the sequence \c within a character class where it is not followed by an acceptable control character.

B.1.2.8.1 CharacterRangeOrUnion ( rer, A, B )

The abstract operation CharacterRangeOrUnion takes arguments rer (a RegExp Record), A (a CharSet), and B (a CharSet) and returns a CharSet. It performs the following steps when called:

  1. If HasEitherUnicodeFlag(rer) is false, then
    1. If A does not contain exactly one character or B does not contain exactly one character, then
      1. Let C be the CharSet containing the single character - U+002D (HYPHEN-MINUS).
      2. Return the union of CharSets A, B and C.
  2. Return CharacterRange(A, B).

B.1.2.9 Static Semantics: ParsePattern ( patternText, u, v )

The semantics of 22.2.3.4 is extended as follows:

The abstract operation ParsePattern takes arguments patternText (a sequence of Unicode code points), u (a Boolean), and v (a Boolean). It performs the following steps when called:

  1. If v is true and u is true, then
    1. Let parseResult be a List containing one or more SyntaxError objects.
  2. Else if v is true, then
    1. Let parseResult be ParseText(patternText, Pattern[+UnicodeMode, +UnicodeSetsMode, +NamedCaptureGroups]).
  3. Else if u is true, then
    1. Let parseResult be ParseText(patternText, Pattern[+UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups]).
  4. Else,
    1. Let parseResult be ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, ~NamedCaptureGroups]).
    2. If parseResult is a Parse Node and parseResult contains a GroupName, then
      1. Set parseResult to ParseText(patternText, Pattern[~UnicodeMode, ~UnicodeSetsMode, +NamedCaptureGroups]).
  5. Return parseResult.

B.2 Additional Built-in Properties

When the ECMAScript host is a web browser the following additional properties of the standard built-in objects are defined.

B.2.1 Additional Properties of the Global Object

The entries in Table 102 are added to Table 6.

Table 102: Additional Well-known Intrinsic Objects
Intrinsic Name Global Name ECMAScript Language Association
%escape% escape The escape function (B.2.1.1)
%unescape% unescape The unescape function (B.2.1.2)

B.2.1.1 escape ( string )

This function is a property of the global object. It computes a new version of a String value in which certain code units have been replaced by a hexadecimal escape sequence.

When replacing a code unit of numeric value less than or equal to 0x00FF, a two-digit escape sequence of the form %xx is used. When replacing a code unit of numeric value strictly greater than 0x00FF, a four-digit escape sequence of the form %uxxxx is used.

It is the %escape% intrinsic object.

It performs the following steps when called:

  1. Set string to ? ToString(string).
  2. Let len be the length of string.
  3. Let R be the empty String.
  4. Let unescapedSet be the string-concatenation of the ASCII word characters and "@*+-./".
  5. Let k be 0.
  6. Repeat, while k < len,
    1. Let C be the code unit at index k within string.
    2. If unescapedSet contains C, then
      1. Let S be C.
    3. Else,
      1. Let n be the numeric value of C.
      2. If n < 256, then
        1. Let hex be the String representation of n, formatted as an uppercase hexadecimal number.
        2. Let S be the string-concatenation of "%" and StringPad(hex, 2, "0", start).
      3. Else,
        1. Let hex be the String representation of n, formatted as an uppercase hexadecimal number.
        2. Let S be the string-concatenation of "%u" and StringPad(hex, 4, "0", start).
    4. Set R to the string-concatenation of R and S.
    5. Set k to k + 1.
  7. Return R.
Note

The encoding is partly based on the encoding described in RFC 1738, but the entire encoding specified in this standard is described above without regard to the contents of RFC 1738. This encoding does not reflect changes to RFC 1738 made by RFC 3986.

B.2.1.2 unescape ( string )

This function is a property of the global object. It computes a new version of a String value in which each escape sequence of the sort that might be introduced by the escape function is replaced with the code unit that it represents.

It is the %unescape% intrinsic object.

It performs the following steps when called:

  1. Set string to ? ToString(string).
  2. Let len be the length of string.
  3. Let R be the empty String.
  4. Let k be 0.
  5. Repeat, while k < len,
    1. Let C be the code unit at index k within string.
    2. If C is the code unit 0x0025 (PERCENT SIGN), then
      1. Let hexDigits be the empty String.
      2. Let optionalAdvance be 0.
      3. If k + 5 < len and the code unit at index k + 1 within string is the code unit 0x0075 (LATIN SMALL LETTER U), then
        1. Set hexDigits to the substring of string from k + 2 to k + 6.
        2. Set optionalAdvance to 5.
      4. Else if k + 3 ≤ len, then
        1. Set hexDigits to the substring of string from k + 1 to k + 3.
        2. Set optionalAdvance to 2.
      5. Let parseResult be ParseText(hexDigits, HexDigits[~Sep]).
      6. If parseResult is a Parse Node, then
        1. Let n be the MV of parseResult.
        2. Set C to the code unit whose numeric value is n.
        3. Set k to k + optionalAdvance.
    3. Set R to the string-concatenation of R and C.
    4. Set k to k + 1.
  6. Return R.

B.2.2 Additional Properties of the String.prototype Object

B.2.2.1 String.prototype.substr ( start, length )

This method returns a substring of the result of converting the this value to a String, starting from index start and running for length code units (or through the end of the String if length is undefined). If start is negative, it is treated as sourceLength + start where sourceLength is the length of the String. The result is a String value, not a String object.

It performs the following steps when called:

  1. Let O be ? RequireObjectCoercible(this value).
  2. Let S be ? ToString(O).
  3. Let size be the length of S.
  4. Let intStart be ? ToIntegerOrInfinity(start).
  5. If intStart = -∞, set intStart to 0.
  6. Else if intStart < 0, set intStart to max(size + intStart, 0).
  7. Else, set intStart to min(intStart, size).
  8. If length is undefined, let intLength be size; otherwise let intLength be ? ToIntegerOrInfinity(length).
  9. Set intLength to the result of clamping intLength between 0 and size.
  10. Let intEnd be min(intStart + intLength, size).
  11. Return the substring of S from intStart to intEnd.
Note

This method is intentionally generic; it does not require that its this value be a String object. Therefore it can be transferred to other kinds of objects for use as a method.

B.2.2.2 String.prototype.anchor ( name )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "a", "name", name).

B.2.2.2.1 CreateHTML ( string, tag, attribute, value )

The abstract operation CreateHTML takes arguments string (an ECMAScript language value), tag (a String), attribute (a String), and value (an ECMAScript language value) and returns either a normal completion containing a String or a throw completion. It performs the following steps when called:

  1. Let str be ? RequireObjectCoercible(string).
  2. Let S be ? ToString(str).
  3. Let p1 be the string-concatenation of "<" and tag.
  4. If attribute is not the empty String, then
    1. Let V be ? ToString(value).
    2. Let escapedV be the String value that is the same as V except that each occurrence of the code unit 0x0022 (QUOTATION MARK) in V has been replaced with the six code unit sequence "&quot;".
    3. Set p1 to the string-concatenation of:
      • p1
      • the code unit 0x0020 (SPACE)
      • attribute
      • the code unit 0x003D (EQUALS SIGN)
      • the code unit 0x0022 (QUOTATION MARK)
      • escapedV
      • the code unit 0x0022 (QUOTATION MARK)
  5. Let p2 be the string-concatenation of p1 and ">".
  6. Let p3 be the string-concatenation of p2 and S.
  7. Let p4 be the string-concatenation of p3, "</", tag, and ">".
  8. Return p4.

B.2.2.3 String.prototype.big ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "big", "", "").

B.2.2.4 String.prototype.blink ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "blink", "", "").

B.2.2.5 String.prototype.bold ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "b", "", "").

B.2.2.6 String.prototype.fixed ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "tt", "", "").

B.2.2.7 String.prototype.fontcolor ( colour )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "font", "color", colour).

B.2.2.8 String.prototype.fontsize ( size )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "font", "size", size).

B.2.2.9 String.prototype.italics ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "i", "", "").

B.2.2.10 String.prototype.link ( url )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "a", "href", url).

B.2.2.11 String.prototype.small ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "small", "", "").

B.2.2.12 String.prototype.strike ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "strike", "", "").

B.2.2.13 String.prototype.sub ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "sub", "", "").

B.2.2.14 String.prototype.sup ( )

This method performs the following steps when called:

  1. Let S be the this value.
  2. Return ? CreateHTML(S, "sup", "", "").

B.2.2.15 String.prototype.trimLeft ( )

Note

The property "trimStart" is preferred. The "trimLeft" property is provided principally for compatibility with old code. It is recommended that the "trimStart" property be used in new ECMAScript code.

The initial value of the "trimLeft" property is %String.prototype.trimStart%, defined in 22.1.3.34.

B.2.2.16 String.prototype.trimRight ( )

Note

The property "trimEnd" is preferred. The "trimRight" property is provided principally for compatibility with old code. It is recommended that the "trimEnd" property be used in new ECMAScript code.

The initial value of the "trimRight" property is %String.prototype.trimEnd%, defined in 22.1.3.33.

B.2.3 Additional Properties of the Date.prototype Object

B.2.3.1 Date.prototype.getYear ( )

Note

The getFullYear method is preferred for nearly all purposes, because it avoids the “year 2000 problem.”

This method performs the following steps when called:

  1. Let dateObject be the this value.
  2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
  3. Let t be dateObject.[[DateValue]].
  4. If t is NaN, return NaN.
  5. Return YearFromTime(LocalTime(t)) - 1900𝔽.

B.2.3.2 Date.prototype.setYear ( year )

Note

The setFullYear method is preferred for nearly all purposes, because it avoids the “year 2000 problem.”

This method performs the following steps when called:

  1. Let dateObject be the this value.
  2. Perform ? RequireInternalSlot(dateObject, [[DateValue]]).
  3. Let t be dateObject.[[DateValue]].
  4. Let y be ? ToNumber(year).
  5. If t is NaN, set t to +0𝔽; otherwise, set t to LocalTime(t).
  6. Let yyyy be MakeFullYear(y).
  7. Let d be MakeDay(yyyy, MonthFromTime(t), DateFromTime(t)).
  8. Let date be MakeDate(d, TimeWithinDay(t)).
  9. Let u be TimeClip(UTC(date)).
  10. Set dateObject.[[DateValue]] to u.
  11. Return u.

B.2.3.3 Date.prototype.toGMTString ( )

Note

The toUTCString method is preferred. This method is provided principally for compatibility with old code.

The initial value of the "toGMTString" property is %Date.prototype.toUTCString%, defined in 21.4.4.43.

B.2.4 Additional Properties of the RegExp.prototype Object

B.2.4.1 RegExp.prototype.compile ( pattern, flags )

This method performs the following steps when called:

  1. Let O be the this value.
  2. Perform ? RequireInternalSlot(O, [[RegExpMatcher]]).
  3. If pattern is an Object and pattern has a [[RegExpMatcher]] internal slot, then
    1. If flags is not undefined, throw a TypeError exception.
    2. Let P be pattern.[[OriginalSource]].
    3. Let F be pattern.[[OriginalFlags]].
  4. Else,
    1. Let P be pattern.
    2. Let F be flags.
  5. Return ? RegExpInitialize(O, P, F).
Note

This method completely reinitializes the this value RegExp with a new pattern and flags. An implementation may interpret use of this method as an assertion that the resulting RegExp object will be used multiple times and hence is a candidate for extra optimization.

B.3 Other Additional Features

B.3.1 Labelled Function Declarations

Prior to ECMAScript 2015, the specification of LabelledStatement did not allow for the association of a statement label with a FunctionDeclaration. However, a labelled FunctionDeclaration was an allowable extension for non-strict code and most browser-hosted ECMAScript implementations supported that extension. In ECMAScript 2015 and later, the grammar production for LabelledStatement permits use of FunctionDeclaration as a LabelledItem but 14.13.1 includes an Early Error rule that produces a Syntax Error if that occurs. That rule is modified with the addition of the highlighted text:

LabelledItem : FunctionDeclaration
  • It is a Syntax Error if any source text that is strict mode code is matched by this production.
Note

The early error rules for WithStatement, IfStatement, and IterationStatement prevent these statements from containing a labelled FunctionDeclaration in non-strict code.

B.3.2 Block-Level Function Declarations Web Legacy Compatibility Semantics

Prior to ECMAScript 2015, the ECMAScript specification did not define the occurrence of a FunctionDeclaration as an element of a Block statement's StatementList. However, support for that form of FunctionDeclaration was an allowable extension and most browser-hosted ECMAScript implementations permitted them. Unfortunately, the semantics of such declarations differ among those implementations. Because of these semantic differences, existing web ECMAScript source text that uses Block level function declarations is only portable among browser implementations if the usage only depends upon the semantic intersection of all of the browser implementations for such declarations. The following are the use cases that fall within that intersection semantics:

  1. A function is declared and only referenced within a single block.

    • One or more FunctionDeclarations whose BindingIdentifier is the name f occur within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g.
    • All occurrences of f as an IdentifierReference are within the StatementList of the Block containing the declaration of f.
  2. A function is declared and possibly used within a single Block but also referenced by an inner function definition that is not contained within that same Block.

    • One or more FunctionDeclarations whose BindingIdentifier is the name f occur within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g.
    • There may be occurrences of f as an IdentifierReference within the StatementList of the Block containing the declaration of f.
    • There is at least one occurrence of f as an IdentifierReference within another function h that is nested within g and no other declaration of f shadows the references to f from within h.
    • All invocations of h occur after the declaration of f has been evaluated.
  3. A function is declared and possibly used within a single block but also referenced within subsequent blocks.

    • One or more FunctionDeclaration whose BindingIdentifier is the name f occur within the function code of an enclosing function g and that declaration is nested within a Block.
    • No other declaration of f that is not a var declaration occurs within the function code of g.
    • There may be occurrences of f as an IdentifierReference within the StatementList of the Block containing the declaration of f.
    • There is at least one occurrence of f as an IdentifierReference within the function code of g that lexically follows the Block containing the declaration of f.

The first use case is interoperable with the semantics of Block level function declarations provided by ECMAScript 2015. Any pre-existing ECMAScript source text that employs that use case will operate using the Block level function declarations semantics defined by clauses 10, 14, and 15.

ECMAScript 2015 interoperability for the second and third use cases requires the following extensions to the clause 10, clause 15, clause 19.2.1 and clause 16.1.7 semantics.

If an ECMAScript implementation has a mechanism for reporting diagnostic warning messages, a warning should be produced when code contains a FunctionDeclaration for which these compatibility semantics are applied and introduce observable differences from non-compatibility semantics. For example, if a var binding is not introduced because its introduction would create an early error, a warning message should not be produced.

B.3.2.1 Changes to FunctionDeclarationInstantiation

During FunctionDeclarationInstantiation the following steps are performed in place of step 29:

  1. If strict is false, then
    1. For each FunctionDeclaration f that is directly contained in the StatementList of any Block, CaseClause, or DefaultClause x such that code Contains x is true, do
      1. Let F be the StringValue of the BindingIdentifier of f.
      2. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for func and parameterNames does not contain F, then
        1. NOTE: A var binding for F is only instantiated here if it is neither a VarDeclaredName, the name of a formal parameter, or another FunctionDeclaration.
        2. If instantiatedVarNames does not contain F and F is not "arguments", then
          1. Perform ! varEnv.CreateMutableBinding(F, false).
          2. Perform ! varEnv.InitializeBinding(F, undefined).
          3. Append F to instantiatedVarNames.
        3. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6:
          1. Let fEnv be the running execution context's VariableEnvironment.
          2. Let bEnv be the running execution context's LexicalEnvironment.
          3. Let fObj be ! bEnv.GetBindingValue(F, false).
          4. Perform ! fEnv.SetMutableBinding(F, fObj, false).
          5. Return unused.

B.3.2.2 Changes to GlobalDeclarationInstantiation

During GlobalDeclarationInstantiation the following steps are performed in place of step 12:

  1. Perform the following steps:
    1. Let strict be ScriptIsStrict of script.
    2. If strict is false, then
      1. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames.
      2. For each FunctionDeclaration f that is directly contained in the StatementList of any Block, CaseClause, or DefaultClause x such that script Contains x is true, do
        1. Let F be the StringValue of the BindingIdentifier of f.
        2. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for script, then
          1. If HasLexicalDeclaration(env, F) is false, then
            1. Let fnDefinable be ? CanDeclareGlobalVar(env, F).
            2. If fnDefinable is true, then
              1. NOTE: A var binding for F is only instantiated here if it is neither a VarDeclaredName nor the name of another FunctionDeclaration.
              2. If declaredFunctionOrVarNames does not contain F, then
                1. Perform ? CreateGlobalVarBinding(env, F, false).
                2. Append F to declaredFunctionOrVarNames.
              3. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6:
                1. Let gEnv be the running execution context's VariableEnvironment.
                2. Let bEnv be the running execution context's LexicalEnvironment.
                3. Let fObj be ! bEnv.GetBindingValue(F, false).
                4. Perform ? gEnv.SetMutableBinding(F, fObj, false).
                5. Return unused.

B.3.2.3 Changes to EvalDeclarationInstantiation

During EvalDeclarationInstantiation the following steps are performed in place of step 13:

  1. If strict is false, then
    1. Let declaredFunctionOrVarNames be the list-concatenation of declaredFunctionNames and declaredVarNames.
    2. For each FunctionDeclaration f that is directly contained in the StatementList of any Block, CaseClause, or DefaultClause x such that body Contains x is true, do
      1. Let F be the StringValue of the BindingIdentifier of f.
      2. If replacing the FunctionDeclaration f with a VariableStatement that has F as a BindingIdentifier would not produce any Early Errors for body, then
        1. Let bindingExists be false.
        2. Let thisEnv be lexEnv.
        3. Assert: The following loop will terminate.
        4. Repeat, while thisEnv is not varEnv,
          1. If thisEnv is not an Object Environment Record, then
            1. If ! thisEnv.HasBinding(F) is true, then
              1. Let bindingExists be true.
          2. Set thisEnv to thisEnv.[[OuterEnv]].
        5. If bindingExists is false and varEnv is a Global Environment Record, then
          1. If HasLexicalDeclaration(varEnv, F) is false, then
            1. Let fnDefinable be ? CanDeclareGlobalVar(varEnv, F).
          2. Else,
            1. Let fnDefinable be false.
        6. Else,
          1. Let fnDefinable be true.
        7. If bindingExists is false and fnDefinable is true, then
          1. If declaredFunctionOrVarNames does not contain F, then
            1. If varEnv is a Global Environment Record, then
              1. Perform ? CreateGlobalVarBinding(varEnv, F, true).
            2. Else,
              1. Let bindingExists be ! varEnv.HasBinding(F).
              2. If bindingExists is false, then
                1. Perform ! varEnv.CreateMutableBinding(F, true).
                2. Perform ! varEnv.InitializeBinding(F, undefined).
            3. Append F to declaredFunctionOrVarNames.
          2. When the FunctionDeclaration f is evaluated, perform the following steps in place of the FunctionDeclaration Evaluation algorithm provided in 15.2.6:
            1. Let gEnv be the running execution context's VariableEnvironment.
            2. Let bEnv be the running execution context's LexicalEnvironment.
            3. Let fObj be ! bEnv.GetBindingValue(F, false).
            4. Perform ? gEnv.SetMutableBinding(F, fObj, false).
            5. Return unused.

B.3.2.4 Changes to Block Static Semantics: Early Errors

The rules for the following production in 14.2.1 are modified with the addition of the highlighted text:

Block : { StatementList }

B.3.2.5 Changes to switch Statement Static Semantics: Early Errors

The rules for the following production in 14.12.1 are modified with the addition of the highlighted text:

SwitchStatement : switch ( Expression ) CaseBlock

B.3.2.6 Changes to BlockDeclarationInstantiation

During BlockDeclarationInstantiation the following steps are performed in place of step 3.a.ii.1:

  1. If ! env.HasBinding(dn) is false, then
    1. Perform ! env.CreateMutableBinding(dn, false).

During BlockDeclarationInstantiation the following steps are performed in place of step 3.b.iii:

  1. Perform the following steps:
    1. If the binding for fn in env is an uninitialized binding, then
      1. Perform ! env.InitializeBinding(fn, fo).
    2. Else,
      1. Assert: d is a FunctionDeclaration.
      2. Perform ! env.SetMutableBinding(fn, fo, false).

B.3.3 FunctionDeclarations in IfStatement Statement Clauses

The following augments the IfStatement production in 14.6:

IfStatement[Yield, Await, Return] : if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else Statement[?Yield, ?Await, ?Return] if ( Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] else FunctionDeclaration[?Yield, ?Await, ~Default] if ( Expression[+In, ?Yield, ?Await] ) FunctionDeclaration[?Yield, ?Await, ~Default] [lookahead ≠ else]

This production only applies when parsing non-strict code. Source text matched by this production is processed as if each matching occurrence of FunctionDeclaration[?Yield, ?Await, ~Default] was the sole StatementListItem of a BlockStatement occupying that position in the source text. The semantics of such a synthetic BlockStatement includes the web legacy compatibility semantics specified in B.3.2.

B.3.4 VariableStatements in Catch Blocks

The content of subclause 14.15.1 is replaced with the following:

Catch : catch ( CatchParameter ) Block Note

The Block of a Catch clause may contain var declarations that bind a name that is also bound by the CatchParameter. At runtime, such bindings are instantiated in the VariableDeclarationEnvironment. They do not shadow the same-named bindings introduced by the CatchParameter and hence the Initializer for such var declarations will assign to the corresponding catch parameter rather than the var binding.

This modified behaviour also applies to var and function declarations introduced by direct eval calls contained within the Block of a Catch clause. This change is accomplished by modifying the algorithm of 19.2.1.3 as follows:

Step 3.d.i.2.a.i is replaced by:

  1. If thisEnv is not the Environment Record for a Catch clause, throw a SyntaxError exception.

Step 13.b.ii.4.a.i.i is replaced by:

  1. If thisEnv is not the Environment Record for a Catch clause, let bindingExists be true.

B.3.5 Initializers in ForIn Statement Heads

The following augments the ForInOfStatement production in 14.7.5:

ForInOfStatement[Yield, Await, Return] : for ( var BindingIdentifier[?Yield, ?Await] Initializer[~In, ?Yield, ?Await] in Expression[+In, ?Yield, ?Await] ) Statement[?Yield, ?Await, ?Return]

This production only applies when parsing non-strict code.

The static semantics of ContainsDuplicateLabels in 8.3.1 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Return ContainsDuplicateLabels of Statement with argument labelSet.

The static semantics of ContainsUndefinedBreakTarget in 8.3.2 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Return ContainsUndefinedBreakTarget of Statement with argument labelSet.

The static semantics of ContainsUndefinedContinueTarget in 8.3.3 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Return ContainsUndefinedContinueTarget of Statement with arguments iterationSet and « ».

The static semantics of IsDestructuring in 14.7.5.2 are augmented with the following:

BindingIdentifier : Identifier yield await
  1. Return false.

The static semantics of VarDeclaredNames in 8.2.6 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Let names1 be the BoundNames of BindingIdentifier.
  2. Let names2 be the VarDeclaredNames of Statement.
  3. Return the list-concatenation of names1 and names2.

The static semantics of VarScopedDeclarations in 8.2.7 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Let declarations1 be « BindingIdentifier ».
  2. Let declarations2 be the VarScopedDeclarations of Statement.
  3. Return the list-concatenation of declarations1 and declarations2.

The runtime semantics of ForInOfLoopEvaluation in 14.7.5.5 are augmented with the following:

ForInOfStatement : for ( var BindingIdentifier Initializer in Expression ) Statement
  1. Let bindingId be the StringValue of BindingIdentifier.
  2. Let lhs be ? ResolveBinding(bindingId).
  3. If IsAnonymousFunctionDefinition(Initializer) is true, then
    1. Let value be ? NamedEvaluation of Initializer with argument bindingId.
  4. Else,
    1. Let rhs be ? Evaluation of Initializer.
    2. Let value be ? GetValue(rhs).
  5. Perform ? PutValue(lhs, value).
  6. Let keyResult be ? ForIn/OfHeadEvaluation(« », Expression, enumerate).
  7. Return ? ForIn/OfBodyEvaluation(BindingIdentifier, Statement, keyResult, enumerate, var-binding, labelSet).

B.3.6 The [[IsHTMLDDA]] Internal Slot

An [[IsHTMLDDA]] internal slot may exist on host-defined objects. Objects with an [[IsHTMLDDA]] internal slot behave like undefined in the ToBoolean and IsLooselyEqual abstract operations and when used as an operand for the typeof operator.

Note

Objects with an [[IsHTMLDDA]] internal slot are never created by this specification. However, the document.all object in web browsers is a host-defined exotic object with this slot that exists for web compatibility purposes. There are no other known examples of this type of object and implementations should not create any with the exception of document.all.

B.3.6.1 Changes to ToBoolean

The following step replaces step 3 of ToBoolean:

  1. If argument is an Object and argument has an [[IsHTMLDDA]] internal slot, return false.

B.3.6.2 Changes to IsLooselyEqual

The following steps replace step 4 of IsLooselyEqual:

  1. Perform the following steps:
    1. If x is an Object, x has an [[IsHTMLDDA]] internal slot, and y is either undefined or null, return true.
    2. If x is either undefined or null, y is an Object, and y has an [[IsHTMLDDA]] internal slot, return true.

B.3.6.3 Changes to the typeof Operator

The following step replaces step 12 of the evaluation semantics for typeof:

  1. If val has an [[IsHTMLDDA]] internal slot, return "undefined".

B.3.7 Non-default behaviour in HostMakeJobCallback

The HostMakeJobCallback abstract operation allows hosts which are web browsers to specify non-default behaviour.

B.3.8 Non-default behaviour in HostEnsureCanAddPrivateElement

The HostEnsureCanAddPrivateElement abstract operation allows hosts which are web browsers to specify non-default behaviour.

Annex C (informative) The Strict Mode of ECMAScript

The strict mode restriction and exceptions

Annex D (informative) Host Layering Points

See 4.2 for the definition of host.

D.1 Host Hooks

HostCallJobCallback(...)

HostEnqueueFinalizationRegistryCleanupJob(...)

HostEnqueueGenericJob(...)

HostEnqueuePromiseJob(...)

HostEnqueueTimeoutJob(...)

HostEnsureCanCompileStrings(...)

HostFinalizeImportMeta(...)

HostGetImportMetaProperties(...)

HostGrowSharedArrayBuffer(...)

HostHasSourceTextAvailable(...)

HostLoadImportedModule(...)

HostGetSupportedImportAttributes(...)

HostMakeJobCallback(...)

HostPromiseRejectionTracker(...)

HostResizeArrayBuffer(...)

InitializeHostDefinedRealm(...)

D.2 Host-defined Fields

[[HostDefined]] on Realm Records: See Table 24.

[[HostDefined]] on Script Records: See Table 39.

[[HostDefined]] on Module Records: See Table 43.

[[HostDefined]] on JobCallback Records: See Table 28.

[[HostSynchronizesWith]] on Candidate Executions: See Table 101.

[[IsHTMLDDA]]: See B.3.6.

D.3 Host-defined Objects

The global object: See clause 19.

D.4 Running Jobs

Preparation steps before, and cleanup steps after, invocation of Job Abstract Closures. See 9.5.

D.5 Internal Methods of Exotic Objects

Any of the essential internal methods in Table 4 for any exotic object not specified within this specification.

D.6 Built-in Objects and Methods

Any built-in objects and methods not defined within this specification, except as restricted in 17.1.

Annex E (informative) Corrections and Clarifications in ECMAScript 2015 with Possible Compatibility Impact

9.1.1.4.14-9.1.1.4.17 Edition 5 and 5.1 used a property existence test to determine whether a global object property corresponding to a new global declaration already existed. ECMAScript 2015 uses an own property existence test. This corresponds to what has been most commonly implemented by web browsers.

10.4.2.1: The 5th Edition moved the capture of the current array length prior to the integer conversion of the array index or new length value. However, the captured length value could become invalid if the conversion process has the side-effect of changing the array length. ECMAScript 2015 specifies that the current array length must be captured after the possible occurrence of such side-effects.

21.4.1.31: Previous editions permitted the TimeClip abstract operation to return either +0𝔽 or -0𝔽 as the representation of a 0 time value. ECMAScript 2015 specifies that +0𝔽 always returned. This means that for ECMAScript 2015 the time value of a Date is never observably -0𝔽 and methods that return time values never return -0𝔽.

21.4.1.32: If a UTC offset representation is not present, the local time zone is used. Edition 5.1 incorrectly stated that a missing time zone should be interpreted as "z".

21.4.4.36: If the year cannot be represented using the Date Time String Format specified in 21.4.1.32 a RangeError exception is thrown. Previous editions did not specify the behaviour for that case.

21.4.4.41: Previous editions did not specify the value returned by Date.prototype.toString when the time value is NaN. ECMAScript 2015 specifies the result to be the String value "Invalid Date".

22.2.4.1, 22.2.6.13.1: Any LineTerminator code points in the value of the "source" property of a RegExp instance must be expressed using an escape sequence. Edition 5.1 only required the escaping of /.

22.2.6.8, 22.2.6.11: In previous editions, the specifications for String.prototype.match and String.prototype.replace was incorrect for cases where the pattern argument was a RegExp value whose global flag is set. The previous specifications stated that for each attempt to match the pattern, if lastIndex did not change, it should be incremented by 1. The correct behaviour is that lastIndex should be incremented by 1 only if the pattern matched the empty String.

23.1.3.30: Previous editions did not specify how a NaN value returned by a comparator was interpreted by Array.prototype.sort. ECMAScript 2015 specifies that such as value is treated as if +0𝔽 was returned from the comparator. ECMAScript 2015 also specifies that ToNumber is applied to the result returned by a comparator. In previous editions, the effect of a comparator result that is not a Number value was implementation-defined. In practice, implementations call ToNumber.

Annex F (informative) Additions and Changes That Introduce Incompatibilities with Prior Editions

6.2.5: In ECMAScript 2015, Function calls are not allowed to return a Reference Record.

7.1.4.1: In ECMAScript 2015, ToNumber applied to a String value now recognizes and converts BinaryIntegerLiteral and OctalIntegerLiteral numeric strings. In previous editions such strings were converted to NaN.

9.3: In ECMAScript 2018, Template objects are canonicalized based on Parse Node (source location), instead of across all occurrences of that template literal or tagged template in a Realm in previous editions.

12.2: In ECMAScript 2016, Unicode 8.0.0 or higher is mandated, as opposed to ECMAScript 2015 which mandated Unicode 5.1. In particular, this caused U+180E MONGOLIAN VOWEL SEPARATOR, which was in the Space_Separator (Zs) category and thus treated as whitespace in ECMAScript 2015, to be moved to the Format (Cf) category (as of Unicode 6.3.0). This causes whitespace-sensitive methods to behave differently. For example, "\u180E".trim().length was 0 in previous editions, but 1 in ECMAScript 2016 and later. Additionally, ECMAScript 2017 mandated always using the latest version of the Unicode Standard.

12.7: In ECMAScript 2015, the valid code points for an IdentifierName are specified in terms of the Unicode properties “ID_Start” and “ID_Continue”. In previous editions, the valid IdentifierName or Identifier code points were specified by enumerating various Unicode code point categories.

12.10.1: In ECMAScript 2015, Automatic Semicolon Insertion adds a semicolon at the end of a do-while statement if the semicolon is missing. This change aligns the specification with the actual behaviour of most existing implementations.

13.2.5.1: In ECMAScript 2015, it is no longer an early error to have duplicate property names in Object Initializers.

13.15.1: In ECMAScript 2015, strict mode code containing an assignment to an immutable binding such as the function name of a FunctionExpression does not produce an early error. Instead it produces a runtime error.

14.2: In ECMAScript 2015, a StatementList beginning with the token let followed by the input elements LineTerminator then Identifier is the start of a LexicalDeclaration. In previous editions, automatic semicolon insertion would always insert a semicolon before the Identifier input element.

14.5: In ECMAScript 2015, a StatementListItem beginning with the token let followed by the token [ is the start of a LexicalDeclaration. In previous editions such a sequence would be the start of an ExpressionStatement.

14.6.2: In ECMAScript 2015, the normal result of an IfStatement is never the value empty. If no Statement part is evaluated or if the evaluated Statement part produces a normal completion containing empty, the result of the IfStatement is undefined.

14.7: In ECMAScript 2015, if the ( token of a for statement is immediately followed by the token sequence let [ then the let is treated as the start of a LexicalDeclaration. In previous editions such a token sequence would be the start of an Expression.

14.7: In ECMAScript 2015, if the ( token of a for-in statement is immediately followed by the token sequence let [ then the let is treated as the start of a ForDeclaration. In previous editions such a token sequence would be the start of an LeftHandSideExpression.

14.7: Prior to ECMAScript 2015, an initialization expression could appear as part of the VariableDeclaration that precedes the in keyword. In ECMAScript 2015, the ForBinding in that same position does not allow the occurrence of such an initializer. In ECMAScript 2017, such an initializer is permitted only in non-strict code.

14.7: In ECMAScript 2015, the result of evaluating an IterationStatement is never a normal completion whose [[Value]] is empty. If the Statement part of an IterationStatement is not evaluated or if the final evaluation of the Statement part produces a normal completion whose [[Value]] is empty, the result of evaluating the IterationStatement is a normal completion whose [[Value]] is undefined.

14.11.2: In ECMAScript 2015, the result of evaluating a WithStatement is never a normal completion whose [[Value]] is empty. If evaluation of the Statement part of a WithStatement produces a normal completion whose [[Value]] is empty, the result of evaluating the WithStatement is a normal completion whose [[Value]] is undefined.

14.12.4: In ECMAScript 2015, the result of evaluating a SwitchStatement is never a normal completion whose [[Value]] is empty. If evaluation of the CaseBlock part of a SwitchStatement produces a normal completion whose [[Value]] is empty, the result of evaluating the SwitchStatement is a normal completion whose [[Value]] is undefined.

14.15: In ECMAScript 2015, it is an early error for a Catch clause to contain a var declaration for the same Identifier that appears as the Catch clause parameter. In previous editions, such a variable declaration would be instantiated in the enclosing variable environment but the declaration's Initializer value would be assigned to the Catch parameter.

14.15, 19.2.1.3: In ECMAScript 2015, a runtime SyntaxError is thrown if a Catch clause evaluates a non-strict direct eval whose eval code includes a var or FunctionDeclaration declaration that binds the same Identifier that appears as the Catch clause parameter.

14.15.3: In ECMAScript 2015, the result of a TryStatement is never the value empty. If the Block part of a TryStatement evaluates to a normal completion containing empty, the result of the TryStatement is undefined. If the Block part of a TryStatement evaluates to a throw completion and it has a Catch part that evaluates to a normal completion containing empty, the result of the TryStatement is undefined if there is no Finally clause or if its Finally clause evaluates to an empty normal completion.

15.4.5 In ECMAScript 2015, the function objects that are created as the values of the [[Get]] or [[Set]] attribute of accessor properties in an ObjectLiteral are not constructor functions and they do not have a "prototype" own property. In the previous edition, they were constructors and had a "prototype" property.

20.1.2.6: In ECMAScript 2015, if the argument to Object.freeze is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.8: In ECMAScript 2015, if the argument to Object.getOwnPropertyDescriptor is not an object an attempt is made to coerce the argument using ToObject. If the coercion is successful the result is used in place of the original argument value. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.10: In ECMAScript 2015, if the argument to Object.getOwnPropertyNames is not an object an attempt is made to coerce the argument using ToObject. If the coercion is successful the result is used in place of the original argument value. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.12: In ECMAScript 2015, if the argument to Object.getPrototypeOf is not an object an attempt is made to coerce the argument using ToObject. If the coercion is successful the result is used in place of the original argument value. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.16: In ECMAScript 2015, if the argument to Object.isExtensible is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.17: In ECMAScript 2015, if the argument to Object.isFrozen is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.18: In ECMAScript 2015, if the argument to Object.isSealed is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.19: In ECMAScript 2015, if the argument to Object.keys is not an object an attempt is made to coerce the argument using ToObject. If the coercion is successful the result is used in place of the original argument value. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.20: In ECMAScript 2015, if the argument to Object.preventExtensions is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.1.2.22: In ECMAScript 2015, if the argument to Object.seal is not an object it is treated as if it was a non-extensible ordinary object with no own properties. In the previous edition, a non-object argument always causes a TypeError to be thrown.

20.2.3.2: In ECMAScript 2015, the [[Prototype]] internal slot of a bound function is set to the [[GetPrototypeOf]] value of its target function. In the previous edition, [[Prototype]] was always set to %Function.prototype%.

20.2.4.1: In ECMAScript 2015, the "length" property of function instances is configurable. In previous editions it was non-configurable.

20.5.6.2: In ECMAScript 2015, the [[Prototype]] internal slot of a NativeError constructor is the Error constructor. In previous editions it was the Function prototype object.

21.4.4 In ECMAScript 2015, the Date prototype object is not a Date instance. In previous editions it was a Date instance whose TimeValue was NaN.

22.1.3.12 In ECMAScript 2015, the String.prototype.localeCompare function must treat Strings that are canonically equivalent according to the Unicode Standard as being identical. In previous editions implementations were permitted to ignore canonical equivalence and could instead use a bit-wise comparison.

22.1.3.28 and 22.1.3.30 In ECMAScript 2015, lowercase/upper conversion processing operates on code points. In previous editions such the conversion processing was only applied to individual code units. The only affected code points are those in the Deseret block of Unicode.

22.1.3.32 In ECMAScript 2015, the String.prototype.trim method is defined to recognize white space code points that may exist outside of the Unicode BMP. However, as of Unicode 7 no such code points are defined. In previous editions such code points would not have been recognized as white space.

22.2.4.1 In ECMAScript 2015, If the pattern argument is a RegExp instance and the flags argument is not undefined, a new RegExp instance is created just like pattern except that pattern's flags are replaced by the argument flags. In previous editions a TypeError exception was thrown when pattern was a RegExp instance and flags was not undefined.

22.2.6 In ECMAScript 2015, the RegExp prototype object is not a RegExp instance. In previous editions it was a RegExp instance whose pattern is the empty String.

22.2.6 In ECMAScript 2015, "source", "global", "ignoreCase", and "multiline" are accessor properties defined on the RegExp prototype object. In previous editions they were data properties defined on RegExp instances.

25.4.15: In ECMAScript 2019, Atomics.wake has been renamed to Atomics.notify to prevent confusion with Atomics.wait.

27.1.6.4, 27.6.3.6: In ECMAScript 2019, the number of Jobs enqueued by await was reduced, which could create an observable difference in resolution order between a then() call and an await expression.

Bibliography

  1. IEEE 754-2019: IEEE Standard for Floating-Point Arithmetic. Institute of Electrical and Electronic Engineers, New York (2019) Note

    There are no normative changes between IEEE 754-2008 and IEEE 754-2019 that affect the ECMA-262 specification.

  2. The Unicode Standard, available at <https://unicode.org/versions/latest>
  3. Unicode Technical Note #5: Canonical Equivalence in Applications, available at <https://unicode.org/notes/tn5/>
  4. Unicode Technical Standard #10: Unicode Collation Algorithm, available at <https://unicode.org/reports/tr10/>
  5. Unicode Standard Annex #15, Unicode Normalization Forms, available at <https://unicode.org/reports/tr15/>
  6. Unicode Standard Annex #18: Unicode Regular Expressions, available at <https://unicode.org/reports/tr18/>
  7. Unicode Standard Annex #24: Unicode Script Property, available at <https://unicode.org/reports/tr24/>
  8. Unicode Standard Annex #31, Unicode Identifiers and Pattern Syntax, available at <https://unicode.org/reports/tr31/>
  9. Unicode Standard Annex #44: Unicode Character Database, available at <https://unicode.org/reports/tr44/>
  10. Unicode Technical Standard #51: Unicode Emoji, available at <https://unicode.org/reports/tr51/>
  11. IANA Time Zone Database, available at <https://www.iana.org/time-zones>
  12. ISO 8601:2004(E) Data elements and interchange formats — Information interchange — Representation of dates and times
  13. RFC 1738 “Uniform Resource Locators (URL)”, available at <https://tools.ietf.org/html/rfc1738>
  14. RFC 2396 “Uniform Resource Identifiers (URI): Generic Syntax”, available at <https://tools.ietf.org/html/rfc2396>
  15. RFC 3629 “UTF-8, a transformation format of ISO 10646”, available at <https://tools.ietf.org/html/rfc3629>
  16. RFC 7231 “Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content”, available at <https://tools.ietf.org/html/rfc7231>

Colophon

This specification is authored on GitHub in a plaintext source format called Ecmarkup. Ecmarkup is an HTML and Markdown dialect that provides a framework and toolset for authoring ECMAScript specifications in plaintext and processing the specification into a full-featured HTML rendering that follows the editorial conventions for this document. Ecmarkup builds on and integrates a number of other formats and technologies including Grammarkdown for defining syntax and Ecmarkdown for authoring algorithm steps. PDF renderings of this specification are produced using a print stylesheet which takes advantage of the CSS Paged Media specification and is converted using PrinceXML.

Prior editions of this specification were authored using Word—the Ecmarkup source text that formed the basis of this edition was produced by converting the ECMAScript 2015 Word document to Ecmarkup using an automated conversion tool.

Copyright & Software License

Ecma International

Rue du Rhone 114

CH-1204 Geneva

Tel: +41 22 849 6000

Fax: +41 22 849 6001

Web: https://ecma-international.org/

Software License

All Software contained in this document ("Software") is protected by copyright and is being made available under the "BSD License", included below. This Software may be subject to third party rights (rights from parties other than Ecma International), including patent rights, and no licenses under such third party rights are granted under this license even if the third party concerned is a member of Ecma International. SEE THE ECMA CODE OF CONDUCT IN PATENT MATTERS AVAILABLE AT https://ecma-international.org/memento/codeofconduct.htm FOR INFORMATION REGARDING THE LICENSING OF PATENT CLAIMS THAT ARE REQUIRED TO IMPLEMENT ECMA INTERNATIONAL STANDARDS.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
  2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
  3. Neither the name of the authors nor Ecma International may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE ECMA INTERNATIONAL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ECMA INTERNATIONAL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.